Вывод IPAddress в HTML

Borman
Offline
Зарегистрирован: 14.01.2016

Помогите, пожалуйста, разобраться:

Глобальной переменной IPAddress LOCAL_IP_ADR присваевается значение 192.168.1.79

При попытке вывести значение в HTML выводится 1325508800

При попытке поставить внутрь анкера (html-ссылки, a href=) - выводит наоборот - 79.1.168.192

#include <ESP8266WiFi.h>

const char* ssid = "BormanSecret";
const char* password = "124borman";
WiFiServer server(80);

int val = 0;
int pinRelay1 = 14;
IPAddress LOCAL_IP_ADR; // ТУТ ОБЪЯВЛЯЕМ ГЛОБАЛЬНУЮ ПЕРЕМЕННУЮ LOCAL_IP_ADR

void setup() {
  Serial.begin(115200);
  delay(10);
  
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  
  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  LOCAL_IP_ADR = WiFi.localIP(); // ПЕРЕДВЁМ В LOCAL_IP_ADR ЗНАЧЕНИЯ
  Serial.println(LOCAL_IP_ADR); // В МОНИТОРЕ ПОРТА ВЫВОДИТСЯ 192.168.1.79
}

void loop() {
  // ПРОВЕРКА ПОДКЛЮЧЕНИЯ КЛИЕНТА
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // ЖДЁМ КЛИЕНТА
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
  
  // ЧТЕНИЕ СТРОКИ ЗАПРОСА
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  
  // ОБРАБОТКА СТРОКИ ЗАПРОСА
  if (req.indexOf("/status") != -1)
    int stat = 1;
  else {
    Serial.println("invalid request");
    client.stop();
    return;
  }
  
  client.flush();

  // ПОДГОТОВКА HTML-страницы
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nRefresh: 5\r\n\r\n<!DOCTYPE HTML>\r\n<meta http-equiv='content-type' content='text/html; charset=UTF-8'>\r\n<title>Данные с датчиков</title>\r\n";
  s += "<html>\r\nЛокальный IP устройства: ";
  s += LOCAL_IP_ADR; // ВЫВОДИТ 1325508800
  s += "<br><a href=http://";
  s += LOCAL_IP_ADR; // ВЫВОДИТ АДРЕС НАОБОРОТ: 79.1.168.192
  s += "/gpio/0>включить</a>";
  s += "</html>\n";

  // ОТПРАВКА СТРАНИЦЫ КЛИЕНТУ
  client.print(s);
  delay(1000);
  Serial.println("Client disonnected");
}

Вобще запутался. Хочется добиться нормального вывода IPAddress внутри строки String при подготовке html-страницы.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Borman,

а с чего Вы взяли, что переменная типа IPAddress должна как-то осмысленно преобразовываться к String?

В сериал он печатается правильно потому, что он поддерживает интерфейс Printable.

Что же до преобразований, то в нём нет операторов преобразования типа. То что в двух местах по-разному - забавно, конечно, но объяснимо - компилятор находит первое подходящее преобразование.

Если Вам нужно осмысленное преобразование IPAddress к String, необходимо добавить его  "ручками".

Borman
Offline
Зарегистрирован: 14.01.2016

Преобразование IPAddress к String совсем не обязательно.

Нужно найти тип переменной для хранения данных типа "192.168.1.79" и вывода данных в String

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ничего не понимаю, так Вам не нужен IPAddress? А зачем использовали? Храните сразу в String, кто не даёт? А если нужен, так добавьте ему преобразование в String (лучше в char *) делов-то.

Borman
Offline
Зарегистрирован: 14.01.2016

bite // WiFi.localIP(); пишет только первый байт айпишника "192"

char // пишет символ "A"

int // понятно, что не будет работать, выдаст те самые "1325508800"

При попытке объявить глобальную String LOCAL_IP_ADR;

компилятор выдаёт ошибку в строке LOCAL_IP_ADR = WiFi.localIP();

exit status 1
ambiguous overload for 'operator=' (operand types are 'String' and 'IPAddress')

 

Borman
Offline
Зарегистрирован: 14.01.2016

String ip_addr = LOCAL_IP_ADR.ToString(); // НЕ РАБОТАЕТ!

ОШИБКА:

'class IPAddress' has no member named 'ToString'

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Простите. Вы уж разберитесь. что Вам надо. Если Вам надо получать значения от WiFi.localIP, то Вам нужен типп IPAddress.

Ну, а если нужен и Вы при этом хотите, чтобы этот IPAddress преобразовывался к строке, Вам просто нужно добавить ему такое преобразование. Ну, нет у него готового.

Или чего Вам надо-то?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Borman пишет:

String ip_addr = LOCAL_IP_ADR.ToString(); // НЕ РАБОТАЕТ!

ОШИБКА:

'class IPAddress' has no member named 'ToString'

Блин, и не будет! Нет у него метода toString! Нет там преобразования - его добавить нужно, я Вам уж полдня про это талдычу.

Borman
Offline
Зарегистрирован: 14.01.2016

НУЖНО:

в СТРОКЕ

выводить значения из

WiFi.localIP();

 

Borman
Offline
Зарегистрирован: 14.01.2016

Ещё интересней: вывод WiFi.localIP(); выдаёт разные значения

  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nRefresh: 5\r\n\r\n<!DOCTYPE HTML>\r\n<meta http-equiv='content-type' content='text/html; charset=UTF-8'>\r\n<title>Данные с датчиков</title>\r\n";
  s += "<html>\r\nЛокальный IP устройства: ";
  s += WiFi.localIP(); // ВЫВОДИТ 1325508800
  s += "<br><a href=http://";
  s += WiFi.localIP(); // ВЫВОДИТ АДРЕС НАОБОРОТ: 79.1.168.192
  s += "/gpio/0>включить</a>";
  s += "</html>\n";

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, а потом нужно преобразовывать IPAddress в строку, так?

Значит нужно добавить ему такое преобразование, т.к. родного у него просто нет.

Borman
Offline
Зарегистрирован: 14.01.2016

Что значит "добавить преобразование"?

Что значит "родное преобразование"?

Borman
Offline
Зарегистрирован: 14.01.2016

14-й час мучаю этот IPAddress...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

У люого класса есть какие-то методы (например, преобразование к другим типам). У класса IPAddress есть методы преобразования к uint32_t и к указателю на uint8_t. А метода преобразования к char * у него нет.

Методы преобразования - обычные функции. Если какой-то нет, надо просто дописать. 

Т.е. Вам нужно, определить новый класс, пронаследованный от IPAddress в котором будет определена функция - преобразование к String (или к char *) и использовать этот класс, а не оригинальный IPAddress.

Вот, собственно и всё.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Borman пишет:

14-й час мучаю этот IPAddress...

а чего его мучать? Вы не умеете переопределять классы? Так Вы себя мучаете, а не его. Сейчас. дайте мне 10 минут, я Вам пример сделаю ...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Можно сделать без добавления метода к классу (просто функция)

#include <ipaddress.h> 

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

char *IPAddress2String(IPAddress & ip) {
	static char str_IP[16];
	char * last = str_IP;
	for (int8_t i = 0; i < 4; i++) {
		itoa(ip[i], last, 10);
		last = last + strlen(last);
		if (i == 3) *last = '\0'; else *last++ = '.';
	}
	return str_IP;
}


IPAddress ip(192,168,1,79);

void setup() {
	Serial.begin(115200);
	String s("IP as char * inside String: ");
	s += IPAddress2String(ip);
	Serial << s << "\n";
}

void loop() {
}

а можно с добавлением метода

#include <ipaddress.h> 

class MyIPAddress : public IPAddress {
public:
	MyIPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) :
		IPAddress(first_octet, second_octet, third_octet, fourth_octet) {}

	operator char * (void) const {
		static char str_IP[16];
			char * last = str_IP;
			for (int8_t i = 0; i < 4; i++) {
				itoa((*this)[i], last, 10);
				last = last + strlen(last);
				if (i == 3) *last = '\0'; else *last++ = '.';
			}
			return str_IP;
		};	
};

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }


MyIPAddress ip(192,168,1,79);

void setup() {
	Serial.begin(115200);
	String s("IP as char * inside String: ");
	s += (char *) ip;
	Serial << s << "\n";
}

void loop() {
}

Выбирайте, как Вам нравится.

Borman
Offline
Зарегистрирован: 14.01.2016

Даже не смог найти документацию по методам IPAddress :(

Наверное, разумнее преобразовывать IPAddress в массив байт, однако конструкция

byte loc_ip[4] = WiFi.localIP()

выдаёт ошибку

exit status 1
array must be initialized with a brace-enclosed initializer

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Borman пишет:

Даже не смог найти документацию по методам IPAddress :(

Наверное, разумнее преобразовывать IPAddress в массив байт, однако конструкция

byte loc_ip[4] = WiFi.localIP()

выдаёт ошибку

exit status 1
array must be initialized with a brace-enclosed initializer

Ну, я Вам уже написал преобразование к char *, Но если Вам хочется к массиву байтов, так у него есть для этого специальный метод - взятие индекса. Типа такого должно работать:

IPAddress ip(192,168,1,79);
uint8_t massiv[4];
for (int8_t i=0; i<4; massiv[i] = ip[i], i++); 

Всё, все четыре числа сидят в массиве.

А документация, так у Вас же его текст есть, чего ещё надо. текст (файлы IPAddress.h и IPAddress.cpp) находится в фолдере <где стоит IDE>\hardware\arduino\avr\cores\arduino  Открываете файлы и смотрите - там всё написано.

Borman
Offline
Зарегистрирован: 14.01.2016

Отлично!

Последний пример - то, что надо: коротко и понятно. С хранением IP в массиве байт разобрался.

Спасибо!

Осталось понять: как байт в unsigned int8 преобразовать в строку?



  String s = char(massiv[0])+".";
  s += char(massiv[1])+".";
  s += char(massiv[2])+".";
  s += char(massiv[3]);
  Serial.println(s);

Выводит ffset: %04x

Borman
Offline
Зарегистрирован: 14.01.2016

Нет ли готового метода преобразования?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, блин, возьмите лучше первый пример из поста 15. Всё равно тоже самое делать. если массив преобразовывать.

Borman
Offline
Зарегистрирован: 14.01.2016

Не совсем то же самое...

В массиве байт удобно хранить данные IPAddress, в том числе писать в ПЗУ.

Однако ещё стоит задача отдать эти данные удалённому пользователю ИЧМ в строке, по HTTP, $_GET и $_POST

а также принять эти данные от пользователя, то же по HTTP $_GET и $_POST.

К сожалению, тут без преобразования byte[] в String и обратно не обойтись...

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Borman пишет:

К сожалению, тут без преобразования byte[] в String и обратно не обойтись...

Ну, не обойтись, так преобразовывайте, только Вы зачем-то их не в String, а в char преобразовываете. Зачем? Замените char на String и будет Вам счастье. Вот так, примерно:

uint8_t massiv[4] = {4,5,6,7};

void setup() {
	Serial.begin(115200);
	String s = String(massiv[0])+".";
	s += String(massiv[1])+".";
	s += String(massiv[2])+".";
	s += String(massiv[3]);
	Serial.println(s);
}

void loop() {
}

 

zalias7
Offline
Зарегистрирован: 18.03.2015

А не пробовали ? String ip_addr = String(WiFi.localIP());

До места доберусь не скоро сам не могу попробовать :)

Borman
Offline
Зарегистрирован: 14.01.2016

ЕвгенийП пишет:

Borman пишет:

К сожалению, тут без преобразования byte[] в String и обратно не обойтись...

Ну, не обойтись, так преобразовывайте, только Вы зачем-то их не в String, а в char преобразовываете. Зачем? Замените char на String и будет Вам счастье. Вот так, примерно:

uint8_t massiv[4] = {4,5,6,7};

void setup() {
	Serial.begin(115200);
	String s = String(massiv[0])+".";
	s += String(massiv[1])+".";
	s += String(massiv[2])+".";
	s += String(massiv[3]);
	Serial.println(s);
}

void loop() {
}

 

Спасибо!

Что-то сам не сообразил... Видать, усталось, надо делать перерывы...

Borman
Offline
Зарегистрирован: 14.01.2016

zalias7 пишет:

А не пробовали ? String ip_addr = String(WiFi.localIP());

До места доберусь не скоро сам не могу попробовать :)

Не работает :(

  Serial.print("IP: ");
  IPAddress LOCAL_IP_ADR = WiFi.localIP();
  Serial.println(LOCAL_IP_ADR); // 192.168.1.79
  
  Serial.print("IP in string: ");
  String ip_addr = String(WiFi.localIP());
  Serial.println(ip_addr);  // 1325508800

По идее - 1325508800 это какая-то операция с 192.168.1.79, только вот понять - какая...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Borman пишет:

По идее - 1325508800 это какая-то операция с 192.168.1.79, только вот понять - какая...

Понятно какая - они рассматриваются как одно 32-разрядное число. Именно его Вы и видите. 

duinor
Offline
Зарегистрирован: 16.01.2016

Переведите 1325508800 в hex  и все сразу встанет на свои места

32 битное делим на 4 части по 8 бит, получается для каждого знака IP выделен 1 байт

1325508800=4F01A8C0h

C0h=192

A8h=168

01h=1

4Fh=79

 

reachim5
Offline
Зарегистрирован: 04.05.2020
 
#include <WiFi.h>

const char* ssid     = "***";
const char* password = "***";
byte raw[4];
String Wi_Fi;
void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  (long&)raw = WiFi.localIP();
  for (byte i = 0; i < 4; i++) {
    Wi_Fi += raw[i];
    Wi_Fi += '.';
  }
Serial.println(Wi_Fi);
}
void loop() {}

 

 

reachim5
Offline
Зарегистрирован: 04.05.2020
byte raw[4];
String Wi_Fi;
(long&)raw = WiFi.localIP();
  for (byte i = 0; i < 4; i++) {
    Wi_Fi += raw[i];
    if(i<3) Wi_Fi += '.';
  }

Извиняюсь, подправил корректное отображение точек

XcLxAd
XcLxAd аватар
Offline
Зарегистрирован: 08.09.2018

ЕвгенийП пишет:

Borman,

а с чего Вы взяли, что переменная типа IPAddress должна как-то осмысленно преобразовываться к String?

IPAddress ipAddress = WiFi.localIP();
ваша функция(String(ipAddress[0]) + '.' + String(ipAddress[1]) + '.' + String(ipAddress[2]) + '.' + String(ipAddress[3]));