852 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			852 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**************************************************************
 | 
						|
 * < Simple Blynk library for WIZnet products >
 | 
						|
 *
 | 
						|
 *   WIZnet official website:	 http://www.wiznet.co.kr
 | 
						|
 *   WIZnet Museum				 http://www.wiznetmuseum.com
 | 
						|
 *   WIZnet Wiki				 http://wizwiki.net
 | 
						|
 *   WIZnet Forum				 http://wizwiki.net/forum
 | 
						|
 *
 | 
						|
 *   Downloads, docs, tutorials: http://www.blynk.cc
 | 
						|
 *   Blynk community:            http://community.blynk.cc
 | 
						|
 *   Social groups:              http://www.fb.com/blynkapp
 | 
						|
 *                               http://twitter.com/blynk_app
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include "socket.h"
 | 
						|
 | 
						|
#include "blynk.h"
 | 
						|
#include "blynkDependency.h"
 | 
						|
#include "../globals.h"
 | 
						|
 | 
						|
//#include "common.h"			// When the project has no "common.h" file, this line have to commented out.
 | 
						|
#ifndef BLYNK_DATA_BUF_SIZE
 | 
						|
	#define BLYNK_DATA_BUF_SIZE	2048
 | 
						|
#endif
 | 
						|
 | 
						|
uint8_t blynk_connect(void);
 | 
						|
void processInput(void);
 | 
						|
void processCmd(uint8_t * buff, size_t len);
 | 
						|
uint8_t readHeader(BlynkHeader * hdr);
 | 
						|
void sendCmd(uint8_t cmd, uint16_t id, uint8_t * data, size_t length, uint8_t * data2, size_t length2);
 | 
						|
 | 
						|
uint16_t getNextMsgId(void);
 | 
						|
void BlynkAverageSample (uint32_t * avg, const uint32_t input, uint8_t n);
 | 
						|
//uint32_t millis(void);
 | 
						|
uint8_t blynk_custom_delay(uint32_t delayms);
 | 
						|
 | 
						|
void blynkparam_init(BlynkParam p);
 | 
						|
uint8_t * blynkparam_get(void);
 | 
						|
 | 
						|
// Util functions
 | 
						|
static uint16_t ATOI(uint8_t * str, uint8_t base);
 | 
						|
static uint8_t C2D(uint8_t c);
 | 
						|
static void replacetonull(uint8_t * str, uint8_t c);
 | 
						|
 | 
						|
static void printBanner();
 | 
						|
 | 
						|
uint8_t * 	authkey;
 | 
						|
uint32_t	lastActivityIn;
 | 
						|
uint32_t	lastActivityOut;
 | 
						|
uint32_t	lastHeartbeat;
 | 
						|
#ifdef BLYNK_MSG_LIMIT
 | 
						|
	uint32_t	deltaCmd;
 | 
						|
#endif
 | 
						|
uint16_t 	currentMsgId;
 | 
						|
 | 
						|
uint8_t blynk_connected = 0;
 | 
						|
uint8_t blynk_connection_available = 0;
 | 
						|
uint32_t ptime = 0;
 | 
						|
 | 
						|
// Init variables
 | 
						|
uint8_t 	blynk_socket, s;
 | 
						|
uint8_t * 	server_ip;
 | 
						|
uint16_t 	server_port;
 | 
						|
uint8_t	*	msgbuf;
 | 
						|
 | 
						|
// variables for parameter parsing
 | 
						|
uint8_t * param_ptr;
 | 
						|
uint8_t * param_end;
 | 
						|
 | 
						|
volatile uint32_t blynk_time_1ms;
 | 
						|
uint16_t	blynkclient_port = BLYNK_DEFAULT_CLIENT_PORT;
 | 
						|
uint8_t		flag_blynkinit_complete = 0;
 | 
						|
 | 
						|
void blynk_begin(uint8_t * auth, uint8_t * dest_ip, uint16_t dest_port, uint8_t * buf, uint8_t socket)
 | 
						|
{
 | 
						|
	s = socket;
 | 
						|
 | 
						|
	authkey = auth;
 | 
						|
	server_ip = dest_ip;
 | 
						|
	server_port = dest_port;
 | 
						|
	msgbuf = buf;
 | 
						|
 | 
						|
	flag_blynkinit_complete = 1;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t blynk_connection_try = 0;
 | 
						|
 | 
						|
void blynk_run(void)
 | 
						|
{
 | 
						|
	uint32_t t;
 | 
						|
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
	uint8_t destip[4];
 | 
						|
	uint16_t destport;
 | 
						|
#endif
 | 
						|
 | 
						|
	if(!flag_blynkinit_complete) return;
 | 
						|
 | 
						|
	switch(getSn_SR(s))
 | 
						|
	{
 | 
						|
		case SOCK_ESTABLISHED:
 | 
						|
			// Interrupt clear
 | 
						|
			if(getSn_IR(s) & Sn_IR_CON)
 | 
						|
			{
 | 
						|
				setSn_IR(s, Sn_IR_CON);
 | 
						|
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
				getSn_DIPR(s, destip);
 | 
						|
				destport = getSn_DPORT(s);
 | 
						|
				PRINTF("Blynk[%d] : Connected - %d.%d.%d.%d:%d\r\n",s, destip[0], destip[1], destip[2], destip[3], destport);
 | 
						|
#endif
 | 
						|
			}
 | 
						|
 | 
						|
			if(!blynk_connected)
 | 
						|
			{
 | 
						|
					if(!(blynk_connection_available = blynk_connect()))	return;
 | 
						|
					else
 | 
						|
					{
 | 
						|
						blynk_connected = true;
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
						PRINTF("Blynk[%d] : Auth connection complete\r\n", s);
 | 
						|
#endif
 | 
						|
						printBanner();
 | 
						|
					}
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
			if(blynk_connection_available > 0) processInput();
 | 
						|
 | 
						|
			t = millis();
 | 
						|
 | 
						|
			if (t - lastActivityIn > (1000UL * BLYNK_HEARTBEAT + BLYNK_TIMEOUT_MS*3)) {
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
				PRINTF("Heartbeat timeout (last in: %lu)\r\n", lastActivityIn);
 | 
						|
#else
 | 
						|
				PRINTF("Heartbeat timeout\r\n");
 | 
						|
#endif
 | 
						|
				blynk_connected = false;
 | 
						|
				blynk_connection_available = false;
 | 
						|
				disconnect(s);
 | 
						|
			}
 | 
						|
			else if ((	t - lastActivityIn	> 1000UL * BLYNK_HEARTBEAT ||
 | 
						|
						t - lastActivityOut	> 1000UL * BLYNK_HEARTBEAT) &&
 | 
						|
						t - lastHeartbeat	> BLYNK_TIMEOUT_MS)
 | 
						|
			{
 | 
						|
				// Send ping if we didn't both send and receive something for BLYNK_HEARTBEAT seconds
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
				PRINTF("Heartbeat\r\n");
 | 
						|
#endif
 | 
						|
				sendCmd(BLYNK_CMD_PING, 0, NULL, 0, NULL, 0);
 | 
						|
				lastHeartbeat = t;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
 | 
						|
		case SOCK_CLOSE_WAIT:
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
		PRINTF("Blynk[%d] : ClOSE WAIT\r\n", s);	// if a peer requests to close the current connection
 | 
						|
#endif
 | 
						|
			disconnect(s);
 | 
						|
			break;
 | 
						|
 | 
						|
		case SOCK_CLOSED:
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
			//PRINTF("> Blynk[%d] : CLOSED\r\n", s);
 | 
						|
#endif
 | 
						|
			blynk_connected = false;
 | 
						|
			blynk_connection_available = false;
 | 
						|
 | 
						|
			if(socket(s, Sn_MR_TCP, blynkclient_port++, 0x00) == s)    /* Reinitialize the socket */
 | 
						|
			{
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
				PRINTF("Blynk[%d] : SOCKET OPEN\r\n", s);
 | 
						|
#endif
 | 
						|
			}
 | 
						|
			break;
 | 
						|
 | 
						|
		case SOCK_INIT:
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
			PRINTF("Blynk[%d] : Connecting to ", s);
 | 
						|
			PRINTF("%d.%d.%d.%d:%d\r\n", server_ip[0], server_ip[1], server_ip[2], server_ip[3], server_port);
 | 
						|
#endif
 | 
						|
			connect(s, server_ip, server_port);
 | 
						|
			break;
 | 
						|
 | 
						|
		default :
 | 
						|
			break;
 | 
						|
 | 
						|
	} // end of switch
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint8_t blynk_connect(void)
 | 
						|
{
 | 
						|
	BlynkHeader hdr;
 | 
						|
	static uint16_t id = 0;
 | 
						|
	uint8_t i;
 | 
						|
	uint8_t hsize = 0;
 | 
						|
//#ifdef BLYNK_DEBUG
 | 
						|
    uint32_t t = millis();
 | 
						|
//#endif
 | 
						|
 | 
						|
    // changed parts
 | 
						|
    //////////////////////////////////////////////////////////////////////////////////
 | 
						|
    static uint8_t cmd_sent = false;
 | 
						|
 | 
						|
    if(blynk_custom_delay(0)) return false;
 | 
						|
 | 
						|
    if(!cmd_sent)
 | 
						|
    {
 | 
						|
    	id = getNextMsgId();
 | 
						|
    	sendCmd(BLYNK_CMD_LOGIN, id, authkey, strlen((char *)authkey), NULL, 0);
 | 
						|
    	cmd_sent = true;
 | 
						|
    	ptime = millis(); // for check connection timeout
 | 
						|
    }
 | 
						|
 | 
						|
    if(millis() < (ptime + BLYNK_CONNECTION_TIMEOUT_MS))	// wait data received during 5sec before connection timeout occur
 | 
						|
    {
 | 
						|
		if(!readHeader(&hdr))
 | 
						|
		{
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		else	// Auth response received
 | 
						|
		{
 | 
						|
			cmd_sent = false;
 | 
						|
		}
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
    	hdr.length = BLYNK_TIMEOUT;
 | 
						|
    	cmd_sent = false;
 | 
						|
    }
 | 
						|
    //////////////////////////////////////////////////////////////////////////////////
 | 
						|
	if (BLYNK_CMD_RESPONSE != hdr.type ||
 | 
						|
		id != hdr.msg_id ||
 | 
						|
		//(BLYNK_SUCCESS != hdr.length && BLYNK_ALREADY_LOGGED_IN != hdr.length)) Deprecated on BLYNK_VERSION 0.6.0
 | 
						|
		(BLYNK_SUCCESS != hdr.length && BLYNK_ILLEGAL_COMMAND_BODY != hdr.length))
 | 
						|
	{
 | 
						|
		if (BLYNK_TIMEOUT == hdr.length)
 | 
						|
		{
 | 
						|
			PRINTF("Timeout\r\n");
 | 
						|
		}
 | 
						|
		else if (BLYNK_INVALID_TOKEN == hdr.length)
 | 
						|
		{
 | 
						|
			PRINTF("Invalid auth token\r\n");
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			PRINTF("Connect failed (code: %d)\r\n", hdr.length);
 | 
						|
 | 
						|
			// Send some invalid headers to server for disconnection
 | 
						|
			hdr.type = 255;
 | 
						|
			hdr.msg_id = 0;
 | 
						|
			hdr.length = 0;
 | 
						|
 | 
						|
			// problem fixed for header structure size
 | 
						|
			hsize = 0;
 | 
						|
			msgbuf[hsize++] = hdr.type;
 | 
						|
			msgbuf[hsize++] = hdr.msg_id;
 | 
						|
			msgbuf[hsize++] = hdr.msg_id;
 | 
						|
			msgbuf[hsize++] = hdr.length;
 | 
						|
			msgbuf[hsize++] = hdr.length;
 | 
						|
			for (i = 0; i < 10; i++)
 | 
						|
			{
 | 
						|
				send(s, msgbuf, hsize);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		disconnect(s);
 | 
						|
		// old delay function removed
 | 
						|
		blynk_custom_delay(5000);
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
    lastHeartbeat = lastActivityIn = lastActivityOut = millis();
 | 
						|
#ifdef BLYNK_MSG_LIMIT
 | 
						|
    deltaCmd = 1000;
 | 
						|
#endif
 | 
						|
 | 
						|
    PRINTF("Ready!\r\n");
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
    PRINTF("Roundtrip: %ldms\r\n", lastActivityIn-t);
 | 
						|
#endif
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
void processInput(void)
 | 
						|
{
 | 
						|
	BlynkHeader hdr;
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
	uint16_t i;
 | 
						|
#endif
 | 
						|
 | 
						|
	if (!readHeader(&hdr)) return;
 | 
						|
 | 
						|
	switch (hdr.type)
 | 
						|
	{
 | 
						|
		case BLYNK_CMD_RESPONSE:
 | 
						|
		{
 | 
						|
			if (BLYNK_NOT_AUTHENTICATED == hdr.length)
 | 
						|
			{
 | 
						|
				disconnect(s);
 | 
						|
				return;
 | 
						|
			}
 | 
						|
		// TODO: return code may indicate App presence
 | 
						|
		} break;
 | 
						|
 | 
						|
		case BLYNK_CMD_PING:
 | 
						|
		{
 | 
						|
			sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS, NULL, 0);
 | 
						|
		} break;
 | 
						|
 | 
						|
		case BLYNK_CMD_HARDWARE:
 | 
						|
		case BLYNK_CMD_BRIDGE:
 | 
						|
		{
 | 
						|
			if (hdr.length > BLYNK_MAX_READBYTES)
 | 
						|
			{
 | 
						|
				PRINTF("Packet size (%u) > max allowed (%u)\r\n", hdr.length, BLYNK_MAX_READBYTES);
 | 
						|
				disconnect(s);
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//PRINTF("hdr.length = %d\r\n", hdr.length);
 | 
						|
			if (hdr.length != recv(s, msgbuf, hdr.length))
 | 
						|
			{
 | 
						|
				PRINTF("Can't read body\r\n");
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			msgbuf[hdr.length] = '\0';	 // Add 1 to zero-terminate
 | 
						|
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
			PRINTF(">");
 | 
						|
			for(i = 0; i < hdr.length; i++)
 | 
						|
			{
 | 
						|
				if(msgbuf[i] != '\0') 	PRINTF("%c", msgbuf[i]);
 | 
						|
				else					PRINTF(" ");
 | 
						|
			}
 | 
						|
			PRINTF("\r\n");
 | 
						|
#endif
 | 
						|
 | 
						|
			currentMsgId = hdr.msg_id;
 | 
						|
			processCmd(msgbuf, hdr.length);
 | 
						|
			currentMsgId = 0;
 | 
						|
		} break;
 | 
						|
//!!  On BLYNK_VERSION 0.6.0 also present (look BlynkProtocol.h bool BlynkProtocol<Transp>::processInput(void)):
 | 
						|
		/*
 | 
						|
		 *
 | 
						|
		case BLYNK_CMD_LOGIN: {..
 | 
						|
 | 
						|
		case BLYNK_CMD_REDIRECT: {..
 | 
						|
 | 
						|
    	case BLYNK_CMD_INTERNAL: {..
 | 
						|
 | 
						|
		case BLYNK_CMD_DEBUG_PRINT: {..
 | 
						|
		 */
 | 
						|
		default:
 | 
						|
			PRINTF("Invalid header type: %d\r\n", hdr.type);
 | 
						|
			disconnect(s);
 | 
						|
			return;
 | 
						|
	}
 | 
						|
 | 
						|
	lastActivityIn = millis();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void blynkparam_init(BlynkParam p)
 | 
						|
{
 | 
						|
	param_ptr = p.buff;
 | 
						|
	param_end = param_ptr + p.len;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint8_t * blynkparam_get(void)
 | 
						|
{
 | 
						|
	uint8_t size;
 | 
						|
	uint8_t * ret_ptr = param_ptr;
 | 
						|
 | 
						|
	if(param_ptr >= param_end) return NULL;
 | 
						|
 | 
						|
	size = strlen((char *)param_ptr);
 | 
						|
	param_ptr += (size+1);
 | 
						|
 | 
						|
	return ret_ptr;
 | 
						|
}
 | 
						|
 | 
						|
void processCmd(uint8_t * buff, size_t len)
 | 
						|
{
 | 
						|
	uint8_t * nexttok;
 | 
						|
	const char * cmd;
 | 
						|
	uint8_t pin;
 | 
						|
	uint8_t rsp_mem[16];
 | 
						|
	uint16_t rsp_len;
 | 
						|
	uint16_t w_param;
 | 
						|
 | 
						|
	BlynkParam param;
 | 
						|
	param.buff = buff;
 | 
						|
	param.len = len;
 | 
						|
 | 
						|
	// for virtual read / write functions
 | 
						|
	//BlynkParam param2;
 | 
						|
	//uint8_t * start;
 | 
						|
 | 
						|
	memset(rsp_mem, 0, sizeof(rsp_mem));
 | 
						|
 | 
						|
	blynkparam_init(param);
 | 
						|
 | 
						|
	nexttok = blynkparam_get();
 | 
						|
	if(!nexttok) return;
 | 
						|
 | 
						|
	cmd = (char *)nexttok;
 | 
						|
 | 
						|
	if(!strcmp(cmd, "info"))
 | 
						|
	{
 | 
						|
		 static uint8_t profile[] =
 | 
						|
				 BLYNK_PARAM_KV("ver"    , BLYNK_VERSION)
 | 
						|
				 BLYNK_PARAM_KV("h-beat" , TOSTRING(BLYNK_HEARTBEAT))
 | 
						|
				 BLYNK_PARAM_KV("buff-in", TOSTRING(BLYNK_MAX_READBYTES))
 | 
						|
#ifdef BLYNK_INFO_DEVICE
 | 
						|
				 BLYNK_PARAM_KV("dev"    , BLYNK_INFO_DEVICE)
 | 
						|
#endif
 | 
						|
#ifdef BLYNK_INFO_CPU
 | 
						|
				 BLYNK_PARAM_KV("cpu"    , BLYNK_INFO_CPU)
 | 
						|
#endif
 | 
						|
#ifdef BLYNK_INFO_CONNECTION
 | 
						|
				 BLYNK_PARAM_KV("con"    , BLYNK_INFO_CONNECTION)
 | 
						|
#endif
 | 
						|
#ifdef BOARD_FIRMWARE_VERSION
 | 
						|
        BLYNK_PARAM_KV("fw"     , BOARD_FIRMWARE_VERSION)
 | 
						|
#endif
 | 
						|
        BLYNK_PARAM_KV("build"  , __DATE__ " " __TIME__)
 | 
						|
        "\0"
 | 
						|
				 ;
 | 
						|
		 const size_t profile_len = sizeof(profile)-1;
 | 
						|
 | 
						|
		 sendCmd(BLYNK_CMD_HARDWARE, 0, profile, profile_len, NULL, 0);
 | 
						|
	}
 | 
						|
 | 
						|
	nexttok = blynkparam_get();
 | 
						|
	if(!nexttok) return;
 | 
						|
 | 
						|
	pin = (uint8_t)ATOI((uint8_t *)nexttok, 10);
 | 
						|
 | 
						|
	if(!strcmp(cmd, "dr")) // digital pin read
 | 
						|
	{
 | 
						|
		//This is bug on LPc13xx original sources, last space symbol is unnecessary
 | 
						|
		//rsp_len = SPRINTF((char *)rsp_mem, "dw %d %d ", pin, digitalRead(pin));
 | 
						|
		rsp_len = SPRINTF((char *)rsp_mem, "dw %d %d", pin, digitalRead(pin));
 | 
						|
		replacetonull(rsp_mem, ' ');
 | 
						|
		sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
	}
 | 
						|
	else if(!strcmp(cmd, "ar")) // analog pin read
 | 
						|
	{
 | 
						|
		//This is bug on LPc13xx original sources, last space symbol is unnecessary (as I think..)
 | 
						|
		//rsp_len = SPRINTF((char *)rsp_mem, "aw %d %d ", pin, analogRead(pin));
 | 
						|
		rsp_len = SPRINTF((char *)rsp_mem, "aw %d %d", pin, analogRead(pin));
 | 
						|
		replacetonull(rsp_mem, ' ');
 | 
						|
		sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
	}
 | 
						|
	else if(!strcmp(cmd, "vr")) // virtual pin read
 | 
						|
	{
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
		PRINTF("vr command: Not fully supported yet\r\n");
 | 
						|
#endif
 | 
						|
		rsp_len = SPRINTF((char *)rsp_mem, "vw %d %d", pin, virtualRead(pin));
 | 
						|
		replacetonull(rsp_mem, ' ');
 | 
						|
		sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
 | 
						|
		/*
 | 
						|
		WidgetReadHandler handler;
 | 
						|
		handler = GetReadHandler(pin);
 | 
						|
		if(handler)
 | 
						|
		{
 | 
						|
			BlynkReq req = { 0, BLYNK_SUCCESS, (uint8_t)pin };
 | 
						|
			handler(req);
 | 
						|
		}
 | 
						|
		*/
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if(!strcmp(cmd, "vw")) // virtual pin write
 | 
						|
		{
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
			PRINTF("vw command: Not fully supported yet\r\n");
 | 
						|
#endif
 | 
						|
			nexttok = blynkparam_get();
 | 
						|
			w_param = ATOI((uint8_t *)nexttok, 10);
 | 
						|
			virtualWrite(pin, w_param);
 | 
						|
 | 
						|
			// update widget state
 | 
						|
			//rsp_len = SPRINTF((char *)rsp_mem, "vw %d %d ", pin, w_param);
 | 
						|
			//replacetonull(rsp_mem, ' ');
 | 
						|
			//sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
 | 
						|
			/*
 | 
						|
			WidgetWriteHandler handler;
 | 
						|
			handler = GetWriteHandler(pin);
 | 
						|
			if(handler)
 | 
						|
			{
 | 
						|
				BlynkReq req = { 0, BLYNK_SUCCESS, (uint8_t)pin };
 | 
						|
 | 
						|
				nexttok = blynkparam_get();
 | 
						|
				start = nexttok;
 | 
						|
 | 
						|
				param2.buff = start;
 | 
						|
				param2.len = len - (start - buff);
 | 
						|
				handler(req, param2);
 | 
						|
			}
 | 
						|
			*/
 | 
						|
		}
 | 
						|
 | 
						|
		if(!strcmp(cmd, "pm")) // pin mode setting
 | 
						|
		{
 | 
						|
			while(nexttok) // end condition: nexttok == NULL
 | 
						|
			{
 | 
						|
				nexttok = blynkparam_get();
 | 
						|
 | 
						|
				if (!strcmp((char *)nexttok, "in")) {
 | 
						|
					pinMode(pin, INPUT);
 | 
						|
				} else if (!strcmp((char *)nexttok, "out") || !strcmp((char *)nexttok, "pwm")) {
 | 
						|
					pinMode(pin, OUTPUT);
 | 
						|
				} else if (!strcmp((char *)nexttok, "pu")) {
 | 
						|
					pinMode(pin, INPUT_PULLUP);
 | 
						|
				} else {
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
					PRINTF("Invalid pinMode %u -> %s\r\n", pin, nexttok);
 | 
						|
#endif
 | 
						|
				}
 | 
						|
				nexttok = blynkparam_get();
 | 
						|
				if(!nexttok) {break;}
 | 
						|
 | 
						|
				pin = (uint8_t)ATOI((uint8_t *)nexttok, 10); // pin info update
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		nexttok = blynkparam_get();
 | 
						|
		if(!nexttok) return;
 | 
						|
 | 
						|
		// Should be 1 parameter (value)
 | 
						|
		if(!strcmp(cmd, "dw")) // digital pin write
 | 
						|
		{
 | 
						|
			w_param = (uint8_t)ATOI((uint8_t *)nexttok, 10);
 | 
						|
 | 
						|
			pinMode(pin, OUTPUT);
 | 
						|
			digitalWrite(pin, w_param ? HIGH : LOW);
 | 
						|
 | 
						|
			// update widget state
 | 
						|
			//rsp_len = SPRINTF((char *)rsp_mem, "dw %d %d ", pin, digitalRead(pin));
 | 
						|
			//replacetonull(rsp_mem, ' ');
 | 
						|
			//sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
		}
 | 
						|
		else if(!strcmp(cmd, "aw")) // analog pin write
 | 
						|
		{
 | 
						|
			w_param = (uint8_t)ATOI((uint8_t *)nexttok, 10);
 | 
						|
 | 
						|
			analogWrite(pin, w_param);
 | 
						|
 | 
						|
			// update widget state
 | 
						|
			//rsp_len = SPRINTF((char *)rsp_mem, "aw %d %d ", pin, digitalRead(pin));
 | 
						|
			//replacetonull(rsp_mem, ' ');
 | 
						|
			//sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			PRINTF("Invalid HW cmd: %s\r\n", cmd);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
uint8_t readHeader(BlynkHeader * hdr)
 | 
						|
{
 | 
						|
	uint16_t len;
 | 
						|
	uint8_t hsize = 0;
 | 
						|
 | 
						|
	if((len = getSn_RX_RSR(s)) > 0)
 | 
						|
	{
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
		//PRINTF("recv header len = %d\r\n", len);
 | 
						|
#endif
 | 
						|
		if(BLINK_HEADER_SIZE != recv(s, msgbuf, BLINK_HEADER_SIZE))
 | 
						|
		{
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		// problem fixed for header structure size
 | 
						|
		hdr->type = msgbuf[hsize++];
 | 
						|
		hdr->msg_id = (uint16_t)msgbuf[hsize++];
 | 
						|
		hdr->msg_id |= ((uint16_t)msgbuf[hsize++]) << 8;
 | 
						|
		hdr->length = (uint16_t)msgbuf[hsize++];
 | 
						|
		hdr->length |= ((uint16_t)msgbuf[hsize++]) << 8;
 | 
						|
 | 
						|
		hdr->msg_id = ntohs(hdr->msg_id);
 | 
						|
		hdr->length = ntohs(hdr->length);
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
		PRINTF(">msg %d,%u,%u\r\n", hdr->type, hdr->msg_id, hdr->length);
 | 
						|
#endif
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
void sendCmd(uint8_t cmd, uint16_t id, uint8_t * data, size_t length, uint8_t * data2, size_t length2)
 | 
						|
{
 | 
						|
	BlynkHeader hdr;
 | 
						|
	size_t wlen = 0;
 | 
						|
	uint32_t ts;
 | 
						|
 | 
						|
	uint8_t hsize = 0;
 | 
						|
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
	uint16_t i;
 | 
						|
#endif
 | 
						|
 | 
						|
	if(getSn_SR(s) != SOCK_ESTABLISHED)
 | 
						|
	{
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
		PRINTF("Cmd not sent\r\n");
 | 
						|
#endif
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
    if (0 == id) {
 | 
						|
        id = getNextMsgId();
 | 
						|
    }
 | 
						|
 | 
						|
    hdr.type = cmd;
 | 
						|
    hdr.msg_id = htons(id);
 | 
						|
    hdr.length = htons(length+length2);
 | 
						|
 | 
						|
    // problem fixed for header structure size
 | 
						|
    msgbuf[hsize++] = hdr.type;
 | 
						|
    msgbuf[hsize++] = (uint8_t)(0x00ff & hdr.msg_id);
 | 
						|
    msgbuf[hsize++] = (uint8_t)((0xff00 & hdr.msg_id) >> 8);
 | 
						|
    msgbuf[hsize++] = (uint8_t)(0x00ff & hdr.length);
 | 
						|
    msgbuf[hsize++] = (uint8_t)((0xff00 & hdr.length) >> 8);
 | 
						|
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
    PRINTF("<msg %d,%u,%u\r\n", cmd, id, length+length2);
 | 
						|
#endif
 | 
						|
 | 
						|
    wlen += (size_t)send(s, msgbuf, hsize);
 | 
						|
 | 
						|
    if (cmd != BLYNK_CMD_RESPONSE) {
 | 
						|
        if (length) {
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
        	PRINTF("<");
 | 
						|
			for(i = 0; i < length; i++)
 | 
						|
			{
 | 
						|
				if(data[i] != '\0') 	PRINTF("%c", data[i]);
 | 
						|
				else					PRINTF(" ");
 | 
						|
			}
 | 
						|
			PRINTF("\r\n");
 | 
						|
#endif
 | 
						|
            wlen += (size_t)send(s, (uint8_t *)data, length);
 | 
						|
        }
 | 
						|
        if (length2) {
 | 
						|
#ifdef BLYNK_DEBUG
 | 
						|
        	PRINTF("<");
 | 
						|
			for(i = 0; i < length2; i++)
 | 
						|
			{
 | 
						|
				if(data2[i] != '\0') 	PRINTF("%c", data2[i]);
 | 
						|
				else					PRINTF(" ");
 | 
						|
			}
 | 
						|
			PRINTF("\r\n");
 | 
						|
#endif
 | 
						|
            wlen += (size_t)send(s, (uint8_t *)data2, length2);
 | 
						|
        }
 | 
						|
        if (wlen != hsize+length+length2) {
 | 
						|
			PRINTF("Sent %u/%u\r\n", wlen, hsize+length+length2);
 | 
						|
			disconnect(s);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
    }
 | 
						|
 | 
						|
    ts = millis();
 | 
						|
#ifdef BLYNK_MSG_LIMIT
 | 
						|
    BlynkAverageSample(&deltaCmd, ts - lastActivityOut, 10);
 | 
						|
    lastActivityOut = ts;
 | 
						|
    if (deltaCmd < (1000/BLYNK_MSG_LIMIT)) {
 | 
						|
		//::delay(5000);
 | 
						|
    	PRINTF("Flood\r\n");
 | 
						|
    	disconnect(s);
 | 
						|
    }
 | 
						|
#else
 | 
						|
    lastActivityOut = ts;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint16_t getNextMsgId(void)
 | 
						|
{
 | 
						|
	static uint16_t last = 0;
 | 
						|
	if (currentMsgId != 0)
 | 
						|
		return currentMsgId;
 | 
						|
	if (++last == 0)
 | 
						|
		last = 1;
 | 
						|
	return last;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void BlynkAverageSample (uint32_t * avg, const uint32_t input, uint8_t n)
 | 
						|
{
 | 
						|
    * avg -=  * avg/n;
 | 
						|
    * avg += input/n;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
uint32_t millis(void)
 | 
						|
{
 | 
						|
	return blynk_time_1ms;
 | 
						|
}
 | 
						|
*/
 | 
						|
 | 
						|
/*
 | 
						|
// Time count function; this function have to call by timer (1ms)
 | 
						|
void blynk_time_handler(void)
 | 
						|
{
 | 
						|
	blynk_time_1ms++;
 | 
						|
}
 | 
						|
*/
 | 
						|
 | 
						|
// Custom delay for checking timeout count
 | 
						|
uint8_t blynk_custom_delay(uint32_t delayms)
 | 
						|
{
 | 
						|
	uint8_t ret = false;
 | 
						|
	static uint32_t basetime;
 | 
						|
 | 
						|
	if(delayms > 0)
 | 
						|
	{
 | 
						|
		if(!basetime) basetime = millis() + delayms;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if(millis() < basetime)
 | 
						|
		{
 | 
						|
			ret = true;		// delaying
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			basetime = 0;
 | 
						|
			ret = false;	// no delay
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
@brief	CONVERT STRING INTO INTEGER
 | 
						|
@return	a integer number
 | 
						|
*/
 | 
						|
static uint16_t ATOI(
 | 
						|
	uint8_t * str,	/**< is a pointer to convert */
 | 
						|
	uint8_t base	/**< is a base value (must be in the range 2 - 16) */
 | 
						|
	)
 | 
						|
{
 | 
						|
        unsigned int num = 0;
 | 
						|
        while ((*str !=0) && (*str != 0x20)) // not include the space(0x020)
 | 
						|
                num = num * base + C2D(*str++);
 | 
						|
	return num;
 | 
						|
}
 | 
						|
 | 
						|
static uint8_t C2D(
 | 
						|
		uint8_t c	/**< is a character('0'-'F') to convert to HEX */
 | 
						|
	)
 | 
						|
{
 | 
						|
	if (c >= '0' && c <= '9')
 | 
						|
		return c - '0';
 | 
						|
	if (c >= 'a' && c <= 'f')
 | 
						|
		return 10 + c -'a';
 | 
						|
	if (c >= 'A' && c <= 'F')
 | 
						|
		return 10 + c -'A';
 | 
						|
 | 
						|
	return (char)c;
 | 
						|
}
 | 
						|
 | 
						|
static void replacetonull(uint8_t * str, uint8_t c)
 | 
						|
{
 | 
						|
	int x;
 | 
						|
	for (x = 0; str[x]; x++)
 | 
						|
		if (str[x] == c) str[x] = NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t is_blynk_connection_available(void)
 | 
						|
{
 | 
						|
	return blynk_connection_available;
 | 
						|
}
 | 
						|
 | 
						|
//Requests Server to re-send current values for all widgets
 | 
						|
void blynk_syncAll(void)
 | 
						|
{
 | 
						|
	sendCmd(BLYNK_CMD_HARDWARE_SYNC, 0, NULL, 0, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
void blynk_push_pin(uint8_t pin)
 | 
						|
{
 | 
						|
	uint8_t rsp_mem[16];
 | 
						|
	uint16_t rsp_len;
 | 
						|
	memset(rsp_mem, 0, sizeof(rsp_mem));
 | 
						|
	rsp_len = SPRINTF((char *)rsp_mem, "dw %d %d", pin, digitalRead(pin));
 | 
						|
	replacetonull(rsp_mem, ' ');
 | 
						|
	sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Sends integer value to a Virtual Pin
 | 
						|
 */
 | 
						|
void blynk_push_virtual_pin(uint8_t pin)
 | 
						|
{
 | 
						|
	uint8_t rsp_mem[16];
 | 
						|
	uint16_t rsp_len;
 | 
						|
	memset(rsp_mem, 0, sizeof(rsp_mem));
 | 
						|
	rsp_len = SPRINTF((char *)rsp_mem, "vw %d %d", pin, virtualRead(pin));
 | 
						|
	replacetonull(rsp_mem, ' ');
 | 
						|
	sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Sends buffer (string message for example) to a Virtual Pin
 | 
						|
 */
 | 
						|
void blynk_push_virtual_pin_msg(uint8_t pin, uint8_t * data)
 | 
						|
{
 | 
						|
	uint8_t rsp_mem[16];
 | 
						|
	uint16_t rsp_len;
 | 
						|
	memset(rsp_mem, 0, sizeof(rsp_mem));
 | 
						|
	rsp_len = SPRINTF((char *)rsp_mem, "vw %d", pin);
 | 
						|
	replacetonull(rsp_mem, ' ');
 | 
						|
	sendCmd(BLYNK_CMD_HARDWARE, 0, rsp_mem, rsp_len+1, data, strlen(data));
 | 
						|
}
 | 
						|
 | 
						|
void BLYNK_LOG_TIME() {
 | 
						|
    PRINTF(BLYNK_NEWLINE "[%lu] ", millis());
 | 
						|
}
 | 
						|
#define BLYNK_LOG1(p1)            { BLYNK_LOG_TIME(); PRINTF(p1); }
 | 
						|
 | 
						|
static void printBanner() {
 | 
						|
#if defined(BLYNK_NO_FANCY_LOGO)
 | 
						|
    BLYNK_LOG1(BLYNK_F("Blynk v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE));
 | 
						|
#else
 | 
						|
    BLYNK_LOG1(BLYNK_NEWLINE
 | 
						|
        "    ___  __          __" BLYNK_NEWLINE
 | 
						|
        "   / _ )/ /_ _____  / /__" BLYNK_NEWLINE
 | 
						|
        "  / _  / / // / _ \\/  '_/" BLYNK_NEWLINE
 | 
						|
        " /____/_/\\_, /_//_/_/\\_\\" BLYNK_NEWLINE
 | 
						|
        "        /___/ v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE BLYNK_NEWLINE
 | 
						|
    );
 | 
						|
#endif
 | 
						|
}
 | 
						|
 |