Заполнение памяти используемое программой.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013
import processing.net.*;



//Связь с Ethernet клиентом и сервером
int html_port = 80;
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
Server server;        
Client client;
int connect_arduino=0;
int connect_server=0;
String list;
//Символ до которого будем считывать данные
byte flag=62;
//Переменные с данными
float [] fl_data=new float [8];
String str_data[]; 
//Вывод данных в график
float xn=420, xk=420, yn1, yk1, yn2, yk2, yn3, yk3, yn4, yk4; 
//Интервал графика 4 мин 1 pix.
long previous_Grafik = 0;
long interval_Grafik = 1000;  
boolean grafik = true;

String climate;

void setup()
{
  size(800, 600);
  background (208, 208, 208);
  for (int i=1; i<8; i++) {
    fl_data[i]=0.0;
  }
}

void draw()
{
  //Прием данных с ардуино
  client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("GET/Processing 2.0 ");
  delay (1000);
  while (client.available()>0){
    if (client !=null) {
      connect_arduino = 1; 
      list = client.readStringUntil(flag);
      if (list != null) {
        str_data = split(list, ';');
      }
      } else {connect_arduino = 0;}
    
    client.stop ();
    
  
  
  //Преобразование string в float
  for (int i=1; i<8; i++){
    if (str_data[i] != null) {fl_data[i]=float(str_data[i]);}
   }   
 
 }
  if(millis() - previous_Grafik > interval_Grafik) {
    previous_Grafik = millis(); 
    print (previous_Grafik);
    yn1=545-15*(fl_data[1]-15);
    yn2=545-2.25*(fl_data[2]);
    yn3=545-15*(fl_data[3]-15);
    yn4=545-15*(fl_data[4]-15);
     if (grafik == true) {
       yk1=yn1;
       yk2=yn2;
       yk3=yn3;
       yk4=yn4;
       grafik = false;
      }
    noStroke (); 
    stroke(208,208,208);
    line (xk+1, 320, xk+1, 545);
    line (xk+3, 320, xk+3, 545);
    line (781, 320, 781, 545);
    stroke(0);
    line (xk+2, 320, xk+2, 545);
    stroke(255, 0, 0);
    line (xn, yn1, xk, yk1);
    stroke(0, 125, 255);
    line (xn, yn2, xk, yk2);
    stroke(128, 0, 0);
    line (xn, yn3, xk, yk3);
    stroke(128, 0, 128);
    line (xn, yn4, xk, yk4);
    yk1=yn1;
    yk2=yn2;
    yk3=yn3;
    yk4=yn4;
    xk=xn;
    xn++;
    if (xn > 780) {xn = 420; xk = 420;}
  }
  
}
 

Получаем данные с Ethernet, переводим в float, рисуем график. Вроде все элементарно и просто. Все работает. Но через сутки непрерывной работы память используеммая программой увеличивается в разы, и вылетает ошибка OutMemoryError. Выкладываю скетч в оригинале, практически пустой, ни чем не перегруженный. Прошу помоч найти проблеммное место, от которого программа в буфере распухает.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Немного отредактировал

import processing.net.*;



//Связь с Ethernet клиентом и сервером
int html_port = 80;
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
Server server;        
Client client;
int connect_arduino=0;
int connect_server=0;
//Символ до которого будем считывать данные
byte flag=62;
//Переменные с данными
float [] fl_data=new float [8];
String [] str_data=new String [8]; 
//Вывод данных в график
float xn=420, xk=420, yn1, yk1, yn2, yk2, yn3, yk3, yn4, yk4; 
//Интервал графика 4 мин 1 pix.
long previous_Grafik = 0;
long interval_Grafik = 1000;  
boolean grafik = true;

String climate;

void setup()
{
  size(800, 600);
  background (208, 208, 208);
  for (int i=1; i<8; i++) {
    fl_data[i]=0.0;
  }
}

void draw()
{
  //Прием данных с ардуино
  client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("GET/Processing 2.0 ");
  delay (1000);
  while (client.available()>0){
    if (client !=null) {
      connect_arduino = 1; 
      String list = client.readStringUntil(flag);
      if (list != null) {
        str_data = split(list, ';');
      }
      } else {connect_arduino = 0;}
    
    client.stop ();
    
  //Преобразование string в float
  for (int i=1; i<8; i++){
    if (str_data[i] != null) {fl_data[i]=float(str_data[i]);}
   }   
 
 }
  if(millis() - previous_Grafik > interval_Grafik) {
    previous_Grafik = millis(); 
    yn1=545-15*(fl_data[1]-15);
    yn2=545-2.25*(fl_data[2]);
    yn3=545-15*(fl_data[3]-15);
    yn4=545-15*(fl_data[4]-15);
     if (grafik == true) {
       yk1=yn1;
       yk2=yn2;
       yk3=yn3;
       yk4=yn4;
       grafik = false;
      }
    stroke(208,208,208);
    line (xk+1, 320, xk+1, 545);
    line (xk+3, 320, xk+3, 545);
    line (781, 320, 781, 545);
    stroke(0);
    line (xk+2, 320, xk+2, 545);
    stroke(255, 0, 0);
    line (xn, yn1, xk, yk1);
    stroke(0, 125, 255);
    line (xn, yn2, xk, yk2);
    stroke(128, 0, 0);
    line (xn, yn3, xk, yk3);
    stroke(128, 0, 128);
    line (xn, yn4, xk, yk4);
    yk1=yn1;
    yk2=yn2;
    yk3=yn3;
    yk4=yn4;
    xk=xn;
    xn++;
    if (xn > 780) {xn = 420; xk = 420;}
  }
 for (int i=1; i<8; i++){
   str_data[i] = null;
 }
}
 

Но проблемма осталась. Память растет.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Client каждый раз создается заново. Либо его надо освобождать, либо создать один раз и использовать. Процессинг не пользую, но, сходу только это. Предполагаю, что метод draw вызывается многократно

leshak
Offline
Зарегистрирован: 29.09.2011

Можете попробовать поискать как в процессинге принудительно вызывать Garbage Collector (раз там джава под капотом - должен быть сборщик). И попробовать его дергать время от времени.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:
Client каждый раз создается заново. Либо его надо освобождать, либо создать один раз и использовать. Процессинг не пользую, но, сходу только это. Предполагаю, что метод draw вызывается многократно
после чтения буфера,  его обработки, клиент отключаетя client.stop();.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

leshak пишет:

Можете попробовать поискать как в процессинге принудительно вызывать Garbage Collector (раз там джава под капотом - должен быть сборщик). И попробовать его дергать время от времени.

попрбовал, что то не помогло, или не так пробую.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Если Вы понимаете разницу между "освободить" память и "остановить" клиента, тогда продолжайте дальше, а если не совсем, тогда посмотрите пример, правда Процессинг 2.0+

import processing.net.*; 
Client myClient; 
int dataIn; 
 
void setup() { 
  size(200, 200); 
  // Connect to the local machine at port 5204.
  // This example will not run if you haven't
  // previously started a server on this port.
  myClient = new Client(this, "127.0.0.1", 5204); 
} 
 
void draw() { 
  if (myClient.available() > 0) { 
    dataIn = myClient.read(); 
  } 
  background(dataIn); 
} 

Думаю разницу видно и без объяснений.

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:

Если Вы понимаете разницу между "освободить" память и "остановить" клиента, тогда продолжайте дальше, а если не совсем, тогда посмотрите пример, правда Процессинг 2.0+

import processing.net.*; 
Client myClient; 
int dataIn; 
 
void setup() { 
  size(200, 200); 
  // Connect to the local machine at port 5204.
  // This example will not run if you haven't
  // previously started a server on this port.
  myClient = new Client(this, "127.0.0.1", 5204); 
} 
 
void draw() { 
  if (myClient.available() > 0) { 
    dataIn = myClient.read(); 
  } 
  background(dataIn); 
} 

Думаю разницу видно и без объяснений.

 

я заю этот пример. Но, к сожалению, при его использоании, вылетает ошибка NullPointerException без выделения конкретной строки с ошибкой. Победить ее не удалось, в том числе через try.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

В таком случае читаем комментарии в примере и видим, что там написано примерно следующее:

// Подключение к локальной машине к порту 5204

// Этот пример не будет работать, если сервер в этот момент не слушает порт 5204.

Далее читаем описание к примеру:

Description	 A client connects to a server and sends data back and forth. If anything goes wrong with the connection, for example the host is not there or is listening on a different port, an exception is thrown.

Что означает примерно следующее:

Описание: Слиент пытается подключиться к серверу ... Если соединение не установлено, например, хост не найден или сервер не слушает порт, возникает exception.

Т.е. Вы хотите сказать, что запуская пример с параметрами (10 строка):

myClient = new Client( this, ""10.168.2.129"", 82 );

у Вас всё равно возникает exception? При этом Ардуино включен и слушает 82 порт? Пинги идут?

Если идут пинги и всё равно возникает exception, тогда я пас, это уже слишком глубоко для меня.

 

leshak
Offline
Зарегистрирован: 29.09.2011

Мемори лики - это самая "вкуснятина" для мазохистов. Тем более в .net/java которые создавались как-бы для того что-бы они стали невозможны в принципе :(

Попробуйте, для начала, выяснить кто у вас "безобразит". Код работы с сетью или код отрисовки. Попробуйте их поочередно закоментить и покрутить в цикле. Выяснить какая половина "течет".

А в отрисовке, кстати тоже оно бывает. Если верить гуглу. И происходить это может - совсем не по вашей вине.

К примеру:

java - Processing 2.0b8 / Disposing PGraphics objects and memory management - Stack Overflow

leshak
Offline
Зарегистрирован: 29.09.2011

Попробуйте еще перед client.stop, следать что-то типа

 if (myClient.available() > 0)  myClient.read(); 
  

Вдруг вам сервер закончил свой ответ не символом "перевод строки". Тогда возможно ваш клиент не доконца вычитал "все что пришло", и не освободил какие-то ресурсы. И где-то остается "буффер" который ждет пока данные примутся целиком.
Еще можно client.clear() сделать (совместно с кодом выше).

leshak
Offline
Зарегистрирован: 29.09.2011

И еще. попрбуйте Client тоже объявить как локальную переменную. Убрать ее из начала скетча, и вмето

client = new Client(this, IP_arduino, arduino_port);

Делать

Client client = new Client(this, IP_arduino, arduino_port);

Что-бы по окончании функции Draw оно понимало что "больше не используем эту переменную" (раз она локальная).

Ну и GC при этом, в профилактических целях - продожать вызывать :)

toc
Offline
Зарегистрирован: 09.02.2013
ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:

В таком случае читаем комментарии в примере и видим, что там написано примерно следующее:

// Подключение к локальной машине к порту 5204

// Этот пример не будет работать, если сервер в этот момент не слушает порт 5204.

Далее читаем описание к примеру:

Description	 A client connects to a server and sends data back and forth. If anything goes wrong with the connection, for example the host is not there or is listening on a different port, an exception is thrown.

Что означает примерно следующее:

Описание: Слиент пытается подключиться к серверу ... Если соединение не установлено, например, хост не найден или сервер не слушает порт, возникает exception.

Т.е. Вы хотите сказать, что запуская пример с параметрами (10 строка):

myClient = new Client( this, ""10.168.2.129"", 82 );

у Вас всё равно возникает exception? При этом Ардуино включен и слушает 82 порт? Пинги идут?

Если идут пинги и всё равно возникает exception, тогда я пас, это уже слишком глубоко для меня.

 

Клиент подключается, считывает одно значение и вылетает в NullPointerException. Графическая часть при этом остается работать, но на одном и том же значении, которое она успела поимать. Дальнейшей связи нет.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Голый код с Clientom грузит память. Код прилагаю.

import processing.net.*;



//Связь с Ethernet клиентом и сервером
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
//Символ до которого будем считывать данные
byte flag=62;
//Переменные с данными
String [] str_data=new String [8]; 


void setup()
{
}

void draw()
{
  //Прием данных с ардуино
  Client client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("1");
  delay (1000);
  while (client.available()>0){
    if (client !=null) {
      String list = client.readStringUntil(flag);
      if (list != null) {
        str_data = split(list, ';');
        list = null;
      }
      } else {}
    
    client.stop ();
    client.clear(); 
}
}

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:

В таком случае читаем комментарии в примере и видим, что там написано примерно следующее:

// Подключение к локальной машине к порту 5204

// Этот пример не будет работать, если сервер в этот момент не слушает порт 5204.

Далее читаем описание к примеру:

Description	 A client connects to a server and sends data back and forth. If anything goes wrong with the connection, for example the host is not there or is listening on a different port, an exception is thrown.

Что означает примерно следующее:

Описание: Слиент пытается подключиться к серверу ... Если соединение не установлено, например, хост не найден или сервер не слушает порт, возникает exception.

Т.е. Вы хотите сказать, что запуская пример с параметрами (10 строка):

myClient = new Client( this, ""10.168.2.129"", 82 );

у Вас всё равно возникает exception? При этом Ардуино включен и слушает 82 порт? Пинги идут?

Если идут пинги и всё равно возникает exception, тогда я пас, это уже слишком глубоко для меня.

 

Сделал по вышеуказанному примеру.



import processing.net.*;



//Связь с Ethernet клиентом и сервером
Client client;
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
//Символ до которого будем считывать данные
byte flag=62;
//Переменные с данными
//String [] str_data=new String [8]; 
String list;

void setup()
{
  client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
}

void draw()
{
  client.write ("1");
  try {
  //Прием данных с ардуино
  while (client.available()>0){
    list = client.readStringUntil(flag);
 //   str_data = split(list, ';');
    client.clear();
   }
  } catch (Exception e) {
    list = null;
  }
  if (list == null) {println ("Null");}
  if (list != null) {println (list);}
}

Что изменилось?Память стоит на месте. Сейчас 17000кБь.

Считывание происходит. Но так же вылетает ошибка, после каждого чтения

Client got end-of-stream.
java.lang.NullPointerException
	at processing.net.Client.write(Unknown Source)
	at processing.net.Client.write(Unknown Source)
	at Grafik.draw(Grafik.java:41)
	at processing.core.PApplet.handleDraw(PApplet.java:2305)
	at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
	at processing.core.PApplet.run(PApplet.java:2176)
	at java.lang.Thread.run(Thread.java:662)

Есть еще мысли? Мои увы кончились.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

В тему призывается великий мастер MAKSIM, да не падают жухлые листья под ЕГО ноги.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Скорее всего падает на Client.write, попробуйте его в try catch, чтобы определиться.

И еще, если flag сразу не появится в буфере, то readStringUntil вернет null

 

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:

Скорее всего падает на Client.write, попробуйте его в try catch, чтобы определиться.

дык уже определились. Уже же дали эксепшн. Попытка чтения за концом потока.

Помоему идея "создать один клиент" - не то это направление. Оно же при создании клиента - устанавливает соединение. Послали GET,  получили ответ - оборвали соединение. После этого любая попытка что-то прочитать - будет давать этот эксепшн. Что логично - соединения нема, а читать пытаемся.. Метода Client.connect - что-то не видно. Только через конструктор. Значит - каждый раз создавать. И пытатся догадатся почему он не освобождает ресурсы при обрыве коннекшина. Вычитывать все БАЙТЫ пришедшие полностью (а не строки), дергать GC и т.п. Причем байты именно вычитывать, а не "очищать буфер" (что-бы серверная часть могла отослать все что хотела целиком и тоже закрыть коннекшн).

Либо... не обрывать коннешн. Подсоеденились и потихоньку читать до потери пульса, когда байты есть. Но это уже зависит от того что на обратной стороне и как оно будет относится к этому (если с той стороны дуина, то на enc28j60 один одновременный конекшн разрешен, если wiznet - до четерых). Ну и в любом случае "обрыв возможен", так что нужно переподсоединятся. 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Что значит "возвращаетт значение void"?

leshak
Offline
Зарегистрирован: 29.09.2011

ingener.solovyev пишет:

Что значит "возвращаетт значение void"?

Значит "ничего не возвращает". Другими словами это не "функция", а "подпрограмма".

leshak
Offline
Зарегистрирован: 29.09.2011
ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

leshak пишет:

void — Википедия

Client.write(Unknown Source) Смущает вот эта часть ошибки. А функция write возвращает void, думал а вдруг здесь проблема.

leshak
Offline
Зарегистрирован: 29.09.2011

Да почему же это смущает? Вы же не пытается что-то получить от функции Client.write(). Просто вызвали - и все.

А сама ошибка у вас на строчку выше.

"Client got end-of-stream."

Вообщем переводим это все как "вы пытаетесь что-то делать с потоком после того как клиент получил символ-конца-потока". Вообщем не нужно пытатся что-то читать/писать в соедининие которое оборванно/закрыто.

А вообще, какой-то он "жутко аскетчиный". Ни тебе проверить состояние соединения, ни event-тов для этого.

Может у вас сервер закрыл соединение, а вы пытаетесь что-то писать в него.

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

leshak пишет:

дык уже определились. Уже же дали эксепшн. Попытка чтения за концом потока.

Честно говоря я не вижу подтверждение слов ТС, что "падает после каждого чтения".

Согласно приложенного ТС журнала exception, падение может происходить именно на write, потому я и предложить "обложить" его try catch, чтобы в этом убедиться.

Само чтение уже заключено в try catch, потому ошибки давать не должно. Впрочем могу и ошибаться, Java для меня побочный язык, редко пользую.

Объясню смысл своих догадок:

1. Раньше в первом скрипте ТС он записывал строку GET/Processing... через write на Ардуино (я так это понимаю)

2. Теперь он посылает "1"

Как сервер (Ардуино?) должен реагировать на эти две *разные* строки? Мы не знаем, хотя, может быть скетч сервера на Ардуино и есть, а я просто его не заметил.

Да, я бы еще, для очистки совести, добавил инициализацию list в setup, типа:
list = null;

А то, к примеру, client.write выведет строку, потом всё, что в try catch нее выполнится, потому что ответа от сервера еще нет, а далее мы проверяем неинициализированную переменную list на null.

ЗЫ На счет соединения, пусть остается как сейчас есть, в примерах я нигде не видел, чтобы Client создавался несколько раз. Для теста это сейчас по барабану и лучше оставить как есть, т.е. создавать один раз в setup.

ЗЫ2 Я бы пока тупо взял сбацал на том же процессинге серверную часть и поигрался, а то так всё непонятно, что за сервер, что он там делает непонятно абсолютно.
 
ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:

leshak пишет:

дык уже определились. Уже же дали эксепшн. Попытка чтения за концом потока.

Честно говоря я не вижу подтверждение слов ТС, что "падает после каждого чтения".

Согласно приложенного ТС журнала exception, падение может происходить именно на write, потому я и предложить "обложить" его try catch, чтобы в этом убедиться.

Само чтение уже заключено в try catch, потому ошибки давать не должно. Впрочем могу и ошибаться, Java для меня побочный язык, редко пользую.

Объясню смысл своих догадок:

1. Раньше в первом скрипте ТС он записывал строку GET/Processing... через write на Ардуино (я так это понимаю)

2. Теперь он посылает "1"

Как сервер (Ардуино?) должен реагировать на эти две *разные* строки? Мы не знаем, хотя, может быть скетч сервера на Ардуино и есть, а я просто его не заметил.

Да, я бы еще, для очистки совести, добавил инициализацию list в setup, типа:
list = null;

А то, к примеру, client.write выведет строку, потом всё, что в try catch нее выполнится, потому что ответа от сервера еще нет, а далее мы проверяем неинициализированную переменную list на null.

ЗЫ На счет соединения, пусть остается как сейчас есть, в примерах я нигде не видел, чтобы Client создавался несколько раз. Для теста это сейчас по барабану и лучше оставить как есть, т.е. создавать один раз в setup.

ЗЫ2 Я бы пока тупо взял сбацал на том же процессинге серверную часть и поигрался, а то так всё непонятно, что за сервер, что он там делает непонятно абсолютно.
 

Скетч ARDUINO 

#include <EtherCard.h>
#include "DHT.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>

// DHT 22
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
float h, t;
char H[5];
char T[5];

//DS18B20
#define ONE_WIRE_BUS 5
#define TEMPERATURE_PRECISION 9
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float t1, t2;
char T1[6];
char T2[6];

//Реле 1шт
int Relay=6;

//EEPROM Уставки сигналов аварий 1-в.пред.темп, 2-н.пред.темп, 3-в.пред.вл.
float sp1, sp2, sp3;
int simbol;
char U1[3], U2[3], U3[3];


//Ethernet
static byte mymac[] = {0x00, 0x04, 0xA3, 0x21, 0xCA, 0x38};
byte Ethernet::buffer[1024];

//временной интервал
long previousMillis = 0;
long interval = 10000;
boolean x=true;
//Уставки
char* climate;

// PROGMEM
char good [] PROGMEM = 
       "good";
char bad [] PROGMEM = 
       "bad"; 
  
//LED ON/OFF, Ethernet_connect
  int LED_ON = 9; //
  int LED_E_C = 3; //
  int brightness = 66;  //яркость светодиода на 1.3v


// SETUP
 void setup () {
  Serial.begin(9600);
  dht.begin();//DHT22
  
  sensors.begin(); //DS18B20
  
  //Реле 1 шт.
    pinMode(Relay, OUTPUT);
    digitalWrite(Relay, HIGH);
    
  //LED ON/OFF, Ethernet_connect
    pinMode(LED_ON, OUTPUT);
    pinMode(LED_E_C, OUTPUT);
    analogWrite(LED_ON, brightness);
         
  //EEPROM
    sp1 = EEPROM.read(1);
    dtostrf(sp1, 2, 0, U1);
    Serial.println (sp1);
    sp2 = EEPROM.read(2);
    dtostrf(sp2, 2, 0, U2);
    Serial.println (sp2);
    sp3 = EEPROM.read(3);
    dtostrf(sp3, 2, 0, U3);
    Serial.println (sp3);
        
  if (!ether.begin(sizeof Ethernet::buffer, mymac, 10)){
  Serial.println( "No");}
  else{ 
   Serial.println("Ok");
   }
  if (!ether.dhcpSetup()){
    Serial.println("No");
    }
  else {
    Serial.println("Ok");
  
  ether.printIp("IP:\t", ether.myip);
  ether.printIp("Mask:\t", ether.mymask);
  ether.printIp("Host:\t", ether.gwip);
  Serial.println();
  ether.hisport = 82;
  analogWrite(LED_E_C, brightness);
  }
 }
  

void loop() {
  
 //Смена уставок
 if(Serial.available()){
    simbol=Serial.read ();
    if (simbol==117) {
      
     byte t[3] = {0, 0, 0};
     for(byte i = 1; i < 4; i++)
     {
       t[i] = Serial.parseInt();
       EEPROM.write(i, t[i]);
     }
      for(byte i = 1; i < 4; i++)
    {
      t[i] = EEPROM.read(i);
      Serial.print(t[i]);
      if(i < 1) Serial.print(',');
      else Serial.println();
    }
   }
  }
  
 //Снятие показаний с датчиков
   //Установка интервала считывания
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval || x==true) {
   previousMillis = currentMillis; 
   x=false;
   //DHT22
   h = dht.readHumidity();
   dtostrf(h, 4, 1, H);
   t = dht.readTemperature();
   dtostrf(t, 4, 1, T);  
  
   //DS18B20
   sensors.requestTemperatures();
   t1 = sensors.getTempCByIndex(0);
   delay (50);
   dtostrf(t1, 5, 2, T1);
   t2 = sensors.getTempCByIndex(1);
   delay (50);
   dtostrf(t2, 5, 2, T2);
    
    Serial.println();
    Serial.print("T= ");
    Serial.println(T);
    Serial.print("H= ");
    Serial.println(H);
    Serial.print("T1= ");
    Serial.println(T1);
    Serial.print("T2= ");
    Serial.println(T2);
 }
   
 //Аварии
  if (t < sp2 || t1 <sp2 || t2 <sp2 || h > sp3) {
   digitalWrite (Relay, HIGH);
   climate=bad;
     } 
       else 
         { if (t > sp1 || t1 > sp1 || t2 > sp1 || h > sp3) {
             digitalWrite (Relay, HIGH);
             climate=bad;
            }
              else
              { 
                digitalWrite (Relay, LOW);
                climate=good;}
         }
    
  //Ethernet
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  
  if(pos) {
  
    
//   Serial.println("---------------------------------------- NEW PACKET ----------------------------------------");
//   Serial.println((char *)Ethernet::buffer + pos);
//   Serial.println("--------------------------------------------------------------------------------------------");
//   Serial.println();
   
        
    BufferFiller bfill = ether.tcpOffset();
    bfill.emit_p(PSTR(";$S;$S;$S;$S;$S;$S;$S;$F;>")
         , T, H, T1, T2, U1, U2, U3, climate);
    ether.httpServerReply(bfill.position());
   }
 }

client.write "1" или client.write "GET/Processing" не имеет значения. Мне GET/Processing был необходим во время отладки скетча ардуино.

client.write заключал в try catch, ошибка не пропала.

leshak
Offline
Зарегистрирован: 29.09.2011

Ну вот. Скорее всего на ether.httpServerReply(bfill.position()); соединение было закрыто. Любая попытка после этого read/write - естественно будет заканчиватся фатально.

Нужно подключатся заново. Вообщем, могу только повторить:

>Помоему идея "создать один клиент" - не то это направление. 

>Значит - каждый раз создавать. И пытатся догадатся почему он не освобождает ресурсы при обрыве коннекшина. Вычитывать все БАЙТЫ пришедшие полностью (а не строки), дергать GC и т.п

А еще смущает $F в   bfill.emit_p(PSTR(";$S;$S;$S;$S;$S;$S;$S;$F;>")

Уже точно не помню, давно не игрался с enc28j60, но кажись $F означает строку из флеша (или значение типа float, не помню). А у вас climate - это обычный char* . Возможно $S более уместен.

Вообщем-то, это не есть причина текущей проблемы, но потом возмжно нужно будет внимательней сюда присмотрется.

leshak
Offline
Зарегистрирован: 29.09.2011

>Голый код с Clientom грузит память. Код прилагаю.

Кстати это тоже "не совсем голый". Голый бы не парсил пришедшие строки.

import processing.net.*;



//Связь с Ethernet клиентом и сервером
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
//Символ до которого будем считывать данные
byte flag=62;



void setup()
{
}

void draw()
{
  //Прием данных с ардуино
  Client client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("1");
  delay (1000);
  while (client.available()>0){
    if (client !=null) {
      String list = client.readStringUntil(flag);
   
    
    client.stop ();
    client.clear(); 
}
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

Или попробуйте вообще вот такое,будет память жрать?

import processing.net.*;



//Связь с Ethernet клиентом и сервером
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
//Символ до которого будем считывать данные
byte flag=62;



void setup()
{
}

void draw()
{
  //Прием данных с ардуино
  Client client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("1");

  delay (1000);



    while (client.available()>0)client.read();  // вычитываем все пришло. пофиг что.

    client.clear();     
    client.stop ();

   delay(1000); // ждем перед следующим запросом


}

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

leshak пишет:

Ну вот. Скорее всего на ether.httpServerReply(bfill.position()); соединение было закрыто. Любая попытка после этого read/write - естественно будет заканчиватся фатально.

Нужно подключатся заново. Вообщем, могу только повторить:

>Помоему идея "создать один клиент" - не то это направление. 

>Значит - каждый раз создавать. И пытатся догадатся почему он не освобождает ресурсы при обрыве коннекшина. Вычитывать все БАЙТЫ пришедшие полностью (а не строки), дергать GC и т.п

А еще смущает $F в   bfill.emit_p(PSTR(";$S;$S;$S;$S;$S;$S;$S;$F;>")

Уже точно не помню, давно не игрался с enc28j60, но кажись $F означает строку из флеша (или значение типа float, не помню). А у вас climate - это обычный char* . Возможно $S более уместен.

Вообщем-то, это не есть причина текущей проблемы, но потом возмжно нужно будет внимательней сюда присмотрется.

$F передает данные символьные char/string, в моем случае либо "good", либо "bad".

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Вот Вам скетч сервера на Processing

import processing.net.*;
Server server;
int server_port = 80;
float r;
int h;
    
void setup()
{
  server = new Server(this, server_port);
  delay(3000);
  size (100, 100);
  background(255);
}

void draw()
{
   for (int i = 0; i < 16; i++) {
   r = random(15, 30);
   h = round (r);}
   
  Client client = server.available();
  if (client !=null) {
    String whatClientSaid = client.readString();
     if (whatClientSaid != null) {
       server.write (";"+h+";>");
       background(255);
       textSize(32);
       fill (0);
       text (h, 50, 50);
       server.disconnect(client);}
  }
}

Если кто то желает так же по тестировать клиент, прошу принять участие.

Скетч клиента ниже, я так же продолжаю попытки и наблюдения.

import processing.net.*;



//Связь с Ethernet клиентом и сервером
Client client;
int arduino_port = 80;
String IP_arduino = "192.168.1.2";//Пишем сюда свой IP адрес сервера
//Символ до которого будем считывать данные
byte flag=62;
//Переменные с данными
//String [] str_data=new String [8]; 
String list;
//Временные интервалы
//long EthernetMillis = 0;
//long Ethernet_interval = 1;

void setup()
{
  
}

void draw()
{
//  long currentMillis = millis();
//  if(currentMillis - EthernetMillis > Ethernet_interval) {
//    EthernetMillis = currentMillis;
client = new Client(this, IP_arduino, arduino_port);
delay (1000);
client.write ("1");
delay (1000);
//  }
  try {
  //Прием данных с ардуино
  while (client.available()>0){
    list = client.readStringUntil(flag);
 //   str_data = split(list, ';');
    client.clear();
   }
  } catch (Exception e) {
    list = null;
  }
  if (list == null) {println ("Null");}
  if (list != null) {println (list);}
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Запустил эти скетчи на процессинг 2.0.2 Win7 x64 всё работает нормально.

Поменял только ip, номер порта на 82. И в клиенте list = null; в setup добавил. А, вру, вместо глобального, сделал Client локальным, как Лешак говорил, это правильно. Если оставить глобальным - выдает exception, но потом работает.

Клиент:

import processing.net.*;

int arduino_port = 82;
String IP_arduino = "127.0.0.1";
byte flag=62;
String list;

void setup()
{
  list = null;
}

void draw()
{
  Client client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("1");
  delay (1000);
  try {
    while (client.available ()>0)
    {
      list = client.readStringUntil(flag);
      client.clear();
    }
  } 
  catch (Exception e) {
    list = null;
  }
  client.stop();
  if (list == null) {
    println ("Null");
  }
  if (list != null) {
    println (list);
  }
}

Сервер:

import processing.net.*;
Server server;
int server_port = 82;
float r;
int h;
    
void setup()
{
  server = new Server(this, server_port);
  delay(3000);
  size (100, 100);
  background(255);
}

void draw()
{
   for (int i = 0; i < 16; i++) {
   r = random(15, 30);
   h = round (r);}
   
  Client client = server.available();
  if (client !=null) {
    String whatClientSaid = client.readString();
     if (whatClientSaid != null) {
       server.write (";"+h+";>");
       background(255);
       textSize(32);
       fill (0);
       text (h, 50, 50);
       server.disconnect(client);}
  }
}

Дальше без меня. Лично я бы заюзал clientEvent & serverEvent и не стал бы на серваке закрывать соединение, как то это по гадски, к тебе пришел гость, ты с ним поговорил, и с какими то словами выдворил его за дверь, а может он еще хотел поговорить. Думаю, что соединение в нормальном обмене должен рвать клиент.

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:

Запустил эти скетчи на процессинг 2.0.2 Win7 x64 всё работает нормально.

Поменял только ip, номер порта на 82. И в клиенте list = null; в setup добавил. А, вру, вместо глобального, сделал Client локальным, как Лешак говорил, это правильно. Если оставить глобальным - выдает exception, но потом работает.

Клиент:

import processing.net.*;

int arduino_port = 82;
String IP_arduino = "127.0.0.1";
byte flag=62;
String list;

void setup()
{
  list = null;
}

void draw()
{
  Client client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("1");
  delay (1000);
  try {
    while (client.available ()>0)
    {
      list = client.readStringUntil(flag);
      client.clear();
    }
  } 
  catch (Exception e) {
    list = null;
  }
  client.stop();
  if (list == null) {
    println ("Null");
  }
  if (list != null) {
    println (list);
  }
}

Сервер:

import processing.net.*;
Server server;
int server_port = 82;
float r;
int h;
    
void setup()
{
  server = new Server(this, server_port);
  delay(3000);
  size (100, 100);
  background(255);
}

void draw()
{
   for (int i = 0; i < 16; i++) {
   r = random(15, 30);
   h = round (r);}
   
  Client client = server.available();
  if (client !=null) {
    String whatClientSaid = client.readString();
     if (whatClientSaid != null) {
       server.write (";"+h+";>");
       background(255);
       textSize(32);
       fill (0);
       text (h, 50, 50);
       server.disconnect(client);}
  }
}

Дальше без меня. Лично я бы заюзал clientEvent & serverEvent и не стал бы на серваке закрывать соединение, как то это по гадски, к тебе пришел гость, ты с ним поговорил, и с какими то словами выдворил его за дверь, а может он еще хотел поговорить. Думаю, что соединение в нормальном обмене должен рвать клиент.

 

что значит "Работает нормально"? Главная проблема решена? Память не копится?

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ну так запустите и проверяйте. Либо опишите Ваш метод проверки памяти.
Работает, это значит, что на сервере отображаются случайные числа в квадратике.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:
Ну так запустите и проверяйте. Либо опишите Ваш метод проверки памяти. Работает, это значит, что на сервере отображаются случайные числа в квадратике.

 

Ваша схема КЛИЕНТА, так же как и моя копит память. Пол часа работы, с 22000КБ до 42000КБ. Вопрос остался открытым. Проблема накопления памяти не решена.

Буду искать.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Это не моя схема, а Ваша, моя схема - создавать клиента в setup и не рубить соединение на сервере, я уже объяснил почему.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:
Это не моя схема, а Ваша, моя схема - создавать клиента в setup и не рубить соединение на сервере, я уже объяснил почему.

Но Ваша схема, при работе с сервером, выдает ошибку

Client got end-of-stream.
java.lang.NullPointerException
	at processing.net.Client.write(Unknown Source)
	at processing.net.Client.write(Unknown Source)
	at Grafik.draw(Grafik.java:41)
	at processing.core.PApplet.handleDraw(PApplet.java:2305)
	at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
	at processing.core.PApplet.run(PApplet.java:2176)
	at java.lang.Thread.run(Thread.java:662)

Которую обойти не получается.

leshak
Offline
Зарегистрирован: 29.09.2011

Схема - подразумевает что ей следуют и сервер и клиент. Когда кто-то один из них работает по одной "схеме", а кто-то "по другой" - получается фигня.

Я уже вроде детально расписывал "почему у вас не получается" (№26).

И вы выборочно очень читаете ответы. "не рубить соединение на сервере" - было проигнорировано.

А уж сколько раз было проигнорировано "попробуйте вычитывать ВСЕ байты" (даже код дал для этого #28), "попробуйте вызвать Garbage Collector" - я уже со счета сбился.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

leshak пишет:

Схема - подразумевает что ей следуют и сервер и клиент. Когда кто-то один из них работает по одной "схеме", а кто-то "по другой" - получается фигня.

Как на enc28j60 осуществить не обрыв связи с клиентом? К сожалению в примерах и статьях такой информации не видел.

leshak пишет:

Я уже вроде детально расписывал "почему у вас не получается" (№26).

Да, я это читал и согласен, но не представляю как зделать иначе.

leshak пишет:

А уж сколько раз было проигнорировано "попробуйте вычитывать ВСЕ байты" (даже код дал для этого #28), "попробуйте вызвать Garbage Collector" - я уже со счета сбился.

Пробовал, попробую еще раз, вместе с вычитыванием всего что прислал сервер. Результаты напишу.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013
import processing.net.*;



//Связь с Ethernet клиентом и сервером
int arduino_port = 80;
String IP_arduino = "88.85.206.140";
//Символ до которого будем считывать данные
byte flag=62;



void setup()
{
}

void draw()
{
  //Прием данных с ардуино
  Client client;
  client = null;
  client = new Client(this, IP_arduino, arduino_port);
  delay (1000);
  client.write ("1");

  delay (1000);



    while (client.available()>0)client.read();  // вычитываем все пришло. пофиг что.

    client.clear();     
    client.stop ();
    System.gc();
    println (client);
    println (client.read());

   delay(1000); // ждем перед следующим запросом


}

Вот код, память грузит.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

21 строку перенесите в 40-ю, по крайней мере система будет знать, что эта память Вам больше не нужна

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:
21 строку перенесите в 40-ю, по крайней мере система будет знать, что эта память Вам больше не нужна

зделал. Она там была, я ее в 21 перенес, чтобы уж наверняка перед созданием нового клиента обнулялась.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

ingener.solovyev пишет:

kisoft пишет:
21 строку перенесите в 40-ю, по крайней мере система будет знать, что эта память Вам больше не нужна

зделал. Она там была, я ее в 21 перенес, чтобы уж наверняка перед созданием нового клиента обнулялась.

Это неправильно, потому что локальный объект создается, Вы его обнуляете (бессмысленно, поскольку он только что появился), затем создаете. А то, что я написал означает, что "я работу с объектом закончил, можно выносить".

UPD: А после того, как мы сообщили, что "можно выносить", сборщик мусор в своё время эту память освободит. А уж через сколько это произойдет - я не подскажу, моих знаний недостаточно.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

kisoft пишет:

ingener.solovyev пишет:

kisoft пишет:
21 строку перенесите в 40-ю, по крайней мере система будет знать, что эта память Вам больше не нужна

зделал. Она там была, я ее в 21 перенес, чтобы уж наверняка перед созданием нового клиента обнулялась.

Это неправильно, потому что локальный объект создается, Вы его обнуляете (бессмысленно, поскольку он только что появился), затем создаете. А то, что я написал означает, что "я работу с объектом закончил, можно выносить".

UPD: А после того, как мы сообщили, что "можно выносить", сборщик мусор в своё время эту память освободит. А уж через сколько это произойдет - я не подскажу, моих знаний недостаточно.

 

тогда System.gc(); имеет смысл поставить после client=null ?

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Кстати println (client); выводит следующее значение: processing.net.Client@12922f6, где 12922f6 каждое новое соединение разное значение.

 
leshak
Offline
Зарегистрирован: 29.09.2011

>тогда System.gc(); имеет смысл поставить после client=null ?

да.

leshak
Offline
Зарегистрирован: 29.09.2011

ingener.solovyev пишет:

Кстати println (client); выводит следующее значение: processing.net.Client@12922f6, где 12922f6 каждое новое соединение разное значение.

Ну так это нормально. "Установили соединение, что-то послали, прочитали ответ, закрыли соединение" - типичное поведение по HTTP протоколу. Запрос-ответ.
leshak
Offline
Зарегистрирован: 29.09.2011

У меня для вас плохие новости :(

Не вы один на это наткнулись :(

Newbie with Out of memory when using client.write() - Processing Forum - так решение и не нашли.

Так же эта проблема находится висит на баг-трекере

Issue 1362 - processing - Recreating Client instance will cause an out-of-memory error - An open source programming language and environment for creating images, animation, and interactions - Google Project Hosting

И как видим - он не отмечена как "решенная". Так что - очень вероятно что это банально "известный баг".

У вас какая версия процессинга, последняя? Если нет - попробуйте на последнюю апгрейднутся, может там пофиксали.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

leshak пишет:

У меня для вас плохие новости :(

Не вы один на это наткнулись :(

Newbie with Out of memory when using client.write() - Processing Forum - так решение и не нашли.

Так же эта проблема находится висит на баг-трекере

Issue 1362 - processing - Recreating Client instance will cause an out-of-memory error - An open source programming language and environment for creating images, animation, and interactions - Google Project Hosting

И как видим - он не отмечена как "решенная". Так что - очень вероятно что это банально "известный баг".

У вас какая версия процессинга, последняя? Если нет - попробуйте на последнюю апгрейднутся, может там пофиксали.

последняя....

 

Как же мне тогда поступить?

leshak
Offline
Зарегистрирован: 29.09.2011

попробуйте, перед client.stop() сделать

this.unregisterMethod("dispose",client);

если будет ругатся что "нет такого метода unregisterMethod", то это означает что у вас старый процессинг. Тогда вот так:

this.unregisterDispose(client);

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

В общем, решение пока такое, Памяти хватает на 5 часов стабильной работы. Буду использовать планировщик задач Windows для перезапуска приложения, ну и ждать когда пофиксят баг.