Створити протокол взаємодії між Blynk-Esp8266-STM32

Думаю що, blynk + STM32, ще довго не буде популярне. Розробники не будуть приділяти цій темі багато часу. Або сподіватись вже коли набереться критична маса користувачів, які хочуть використовувати STM32 разом з Blynk, тоді з’являться і приклади і бібліотеки. Наголошую що STM32-Arduino та Mbed мене не цікавлять взагалі і вважаю то великою дурницею.

На цей час для себе бачу один вихід - це:

  • як blynk добре працює і підтримується на ESP8266, то хай там і працює. Бере на себе підтримку зв’язку і взаімодію з сервером і мережею.
  • вся інша логіка роботи з периферією хай буде на моєму улюбленому MCU STM32.
  • STM32 і ESP8266 з’єднати між собою по UART або SPI.
  • створити якийсь “універсальний” протокол обміну між цими MCU для взаімодії.

Поки що питання в мене по останньому пункту. Як побудувати взаємозв’язок між ESP8266 і STM32 (чи будь який інший MCU, наприклад, PIC), щоб firmware на esp8266 не переписувати кожного разу коли робити якісь зміни на STM32 чи конфігурації периферії. А було б якось універсально. Наприклад, я до STM32 додав датчик температури і його показники хочу відправити на шпильку V10. Пересилаю з STM32 на ESP8266 данні про температуру і на яку шпильку потрібно. І лізти в код ESP8266 не треба прописуючі відправку даних на шпильку V10. А ESP8266 вже знає що робити з тим і надсилає до blynk. А також навпаки при змінах зі сторони серверу, щоб прийнявши ESP8266 відповідні зміни надіслав це до STM32. А вже STM32 вже знає для чого ті данні.

На загал, виходить потрібна ще така собі бібліотека “протокол-прокладка” для взаємодії між Blynk <-> ESP8266 <-> other MCU.

Такий варіант мене б дуже влаштував. Навіть бачу багато переваг в такому рішенні. І великий потенціал. Та все більшої популяризації системи blynk серед розробників.

В мене немає поки ще ідей як це реалізувати. Може кому сподобалась таке рішення поміркуємо як це організувати?

@vshymanskyy може тебе це зацiкавить?

@Pavel не цікавить, але то таке, справа добровільна.

to all:
Вже сам розпочав в цьому напрямку. Потребую допомоги.
На v40 - terminal widget, v0 - labeled widget, v1 - value widget
З stm32 відправляю пакети даних до esp8266 з номером шпильки і самі дані
Наприклад так:

char* value = "Button pressed!\n";
Blynk_virtualWrite(V40, value, strlen(value));
Blynk_virtualWrite(V0, value, strlen(value));
Blynk_virtualWrite(V1, value, strlen(value));

Є функція на esp8266 яка приймає від stm32 пакет даних де вказано для якої шпильки і самі дані. І esp8266 пересилає це все вже до серверу блінка засобами бібліотеки blynk, наприклад отак, Нас цікавить тільки масив чарів data і розмір масиву size, все інше то стосується внутрішнього міжплатного протоколу:

void data_received(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size)
{
	if (command == MYHIOT_COMMAND_BLYNK)
	{
		Blynk.virtualWriteBinary(data[0], (data + 1), size - 1);				
	}
}

Де data[0] - номер шпильки, а з data +1 - дані обмежені size
В такому вигляді текст “Button pressed!\n” коректно показується На v40 - terminal widget, v0 - labeled widget, v1 - value widget

Якщо мені потрібно змінити стан v20 - button widget то посилаю з stm32 таку команду:

//щоб віджет кнопки був увімкнений
uint8_t state = 1;
Blynk_virtualWrite(V20, (char *) &state, 1);
//щоб віджет кнопки був вимкнений
uint8_t state = 0;
Blynk_virtualWrite(V20, (char *) &state, 1);

Якщо я пересилаю з esp8266 до blynk таким же ж чином:

void data_received(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size)
{
	if (command == MYHIOT_COMMAND_BLYNK)
	{
		Blynk.virtualWriteBinary(data[0], (data + 1), size - 1);				
	}
}

де data[0] - номер шпильки, а з data + 1 (т.е. data[1]) стан кнопки.
В такому випадку в мене віджет кнопки тільки скидається (змінює стан з 1 на 0), а з 0 на 1 стан не міняється.
Але якщо я перенаправляю з esp8266 до серверу blynk тупо в лоб вказавши де брати стан кнопки в масиві:

void data_received(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size)
{
	if (command == MYHIOT_COMMAND_BLYNK)
	{
		Blynk.virtualWrite(data[0], data[1]);
	}
}

То віджет кнопки правильно реагує на зміну стану.

Допоможіть розібратись чому так стається і як зробить правильно? Як бути з int і float, ще навіть не думав.

Тааак, трішки розібрався. Поки зробив під кожен тип змінних окрему функцію. Не знаю як це втілити в одну.

Зі сторони STM32:

void Blynk_virtualWriteInt(int pin, int value)
{
	char dataToBlynk[MYHIOT_SEND_BUFFER_SIZE - MYHIOT_OFFSET_DATA];

	dataToBlynk[BLYNK_OFFSET_PIN] = pin;
	dataToBlynk[BLYNK_OFFSET_TYPE_DATA] = BLYNK_TYPE_INT;

	char *pValue;
	pValue = (char *) &value;

	uint8_t i;
	for (i = 0; i < sizeof(int); i++)
	{
		dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = *(pValue++);
	}

	myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, dataToBlynk, sizeof(int) + BLYNK_OFFSET_DATA_PIN);
}

void Blynk_virtualWriteFloat(int pin, float value)
{
	char dataToBlynk[MYHIOT_SEND_BUFFER_SIZE - MYHIOT_OFFSET_DATA];

	dataToBlynk[BLYNK_OFFSET_PIN] = pin;
	dataToBlynk[BLYNK_OFFSET_TYPE_DATA] = BLYNK_TYPE_FLOAT;

	char *pValue;
	pValue = (char *) &value;

	uint8_t i;
	for (i = 0; i < sizeof(float); i++)
	{
		dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = *(pValue++);
	}

	myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, dataToBlynk, sizeof(float) + BLYNK_OFFSET_DATA_PIN);
}

void Blynk_virtualWriteString(int pin, char* value, uint8_t size)
{
	char dataToBlynk[MYHIOT_SEND_BUFFER_SIZE - MYHIOT_OFFSET_DATA];

	dataToBlynk[BLYNK_OFFSET_PIN] = pin;
	dataToBlynk[BLYNK_OFFSET_TYPE_DATA] = BLYNK_TYPE_CHAR;

	uint8_t i;
	for (i = 0; i < size; i++)
	{
		dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = *(value++);
	}

	myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, dataToBlynk, size + BLYNK_OFFSET_DATA_PIN);
}

Зі сторони ESP8266:

if (command == MYHIOT_COMMAND_BLYNK)
{		
	if (data[BLYNK_OFFSET_TYPE_DATA] == BLYNK_TYPE_INT)
	{						
		int myInt;
		memcpy(&myInt, data + BLYNK_OFFSET_DATA_PIN, sizeof(myInt));
		Blynk.virtualWrite(data[BLYNK_OFFSET_PIN], myInt);
	}
	else if (data[BLYNK_OFFSET_TYPE_DATA] == BLYNK_TYPE_FLOAT)
	{
		float myFloat;		
		memcpy(&myFloat, data + BLYNK_OFFSET_DATA_PIN, sizeof(myFloat));						
		Blynk.virtualWrite(data[BLYNK_OFFSET_PIN], myFloat);
	}
	else if (data[BLYNK_OFFSET_TYPE_DATA] == BLYNK_TYPE_CHAR)
	{
		Blynk.virtualWriteBinary(data[BLYNK_OFFSET_PIN], data + BLYNK_OFFSET_DATA_PIN, size -BLYNK_OFFSET_DATA_PIN);
	}

Ну і на STM32 роблю відправку так:

if(!HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) && !triggerPressedButton)
	  {
		  triggerPressedButton = true;
		  HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);

		  if(HAL_GPIO_ReadPin(LD3_GPIO_Port, LD3_Pin))
		  {
			  //TODO: відправка команди увімкнути щось
			  Blynk_virtualWriteInt(V20, 1);
			  Blynk_virtualWriteInt(V0, -754);
			  Blynk_virtualWriteFloat(V1, -75.45689);
			  char* value = "LED is ON\n";
			  Blynk_virtualWriteString(V40, value, strlen(value));
		  }
		  else
		  {
			  //TODO: відправка команди вимкнути щось
			  Blynk_virtualWriteInt(V20, 0);
			  Blynk_virtualWriteInt(V0, 40569);
			  Blynk_virtualWriteFloat(V1, 40.23);
			  char* value = "LED is OFF\n";
			  Blynk_virtualWriteString(V40, value, strlen(value));
		  }
	  }
	  else if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) && triggerPressedButton)
	  {
		  triggerPressedButton = false;
	  }

Все коректно відтворюється.


Йдемо далі.

2 Likes

Діло йде, але я не розумію одну річ.
Як працює ця магія, коли оголошується в програмі функція:

BLYNK_WRITE(vPIN)
{

}

То коли є зміни на тій шпильки зі сторони серверу та функція викликається.
Я собі для прикладу, що б зрозуміти роботу оголосив макрос:

#define BLYNK_WRITE_MY(pin) void Blynk_Write ## pin(void)

Тобто якщо я оголошую функцію в програмі:

BLYNK_WRITE_MY(0)
{
  //TODO:
}

То це розгортається в:

void Blynk_Write0(void)
{
   //TODO:
}

Ну а як вже цю функцію викликати? Як передати те що я прийняв від шпильки 0?
Як це зроблено в blynk я очима бачу, але розумом ще не розумію. Хоч куди гуглити? Напрямок?

Thanks to the Blynk Library running in the background and the Blynk.run() command in the void loop() combined with Blynk’s connection management ← clickable link. These Blynk made functions just ‘know’ how to respond when the assiciated vPin is used.

And the value of that vPin is determined by a param.as___ command inside that function… (See Virtual Pin Types in link above).

BLYNK_WRITE(V0) // <-- assigned vPin that matches a Widget in the App
{   
  int value = param.asInt(); // Get value as integer

  // The param can contain multiple values from certain widgets (zeRGBa, Joystick, etc.), in such case:
  int x = param[0].asInt();
  int y = param[1].asInt();

  // do stuff with those values with your code here
}