GyverPortal
GyverPortal copied to clipboard
Графики JQuery
Раз в новый портал внедряется возможность юзать jquery, решил исследовать Инет на предмет графиков с использованием данной библиотеки. http://www.flotcharts.org/downloads/ Вот это мне понравилось, даже сейчас скажу чем именно понравилось:
- Все твои скрипты на создание различных графиков занимают 1,58 МБ, а все сжатые скрипты FLOT всего 156 кБ
- Проверил совместимость флот с актуальной версией jquery, всё отлично работает.
- Много примеров и на сколько я понимаю, это очень мощный и гибкий инструмент, есть документация и много примеров Просто как вариант, сам у себя пока не использую графики в проекте, но а вдруг эта идея тебе понравится.
Все твои скрипты на создание различных графиков занимают 1,58 М
Все три типа графиков никто не будет юзать в одном проекте. На данный момент у меня переделана опять файловая система, и файлы графиков больше не дублируются несколько раз в папках
Да я просто, скачал сегодня эту штуку, посмотрел каких там только графиков нет.... Доберусь до других проектов, посмотрю на графики. До сих пор ещё не попробовал
А так добавим ессесн. Я их в принципе видел, это самые популярные веб графики
Вообще мне понравилось как работает лог. То есть подключаем буфер и пишем в него данные, потом буфер выводим в лог. Может так же сделать, там где запускаем портал, делаем для для графика количество линий, количество точек по x,y... А в конструкторе просто объявляем график, указывая его дополнительные параметры.
Может и так, это будет уже полноценный крупный модуль. И будут проблемы с типами данных, но они в целом решаемы
Намучался в усмерть, но однако получилось сделать часть кода.
Лолллл
Не спешите смеяться раньше времени, сейчас немного код причешу, думаю моя затея будет по душе!
Конечно по душе) просто графики выглядят как бык нассал) это чисто по точкам строится, без привязки к одной оси как времени?
нет, это я строю таким макаром
if (millis() - tmr > 1000) {
tmr = millis();
portal.flot.write(0,random(1000),random(1000));
portal.flot.write(1,random(1000),random(1000));
portal.flot.write(2,random(1000),random(1000));
x и y делаю рандомно, можно привязать к millis()
Не, так не пойдет. Нужно делать отдельный класс графика, и дать возможность билдеру его выводить напрямую от объекта
да я вроде так и делал flot.zip да я бы без класса просто сдох бы сегодня Вывод пока черз одно место, но я просто тестировал
void GP_FLOT(GyverPortal& portal){
int _a[]={0,1,2,3};
byte _j=0;
String s;
s.reserve(1000);
s+=F("<link href='/GP_flot.css' rel='stylesheet' type='text/css'>\n"
"<script language='javascript' src='/GP_jquery.js'></script>\n"
"<script language='javascript' src='/GP_flot.js'></script>\n"
"<script>\n$(function(){\n");
while (_j<3){
s+=F("var d");
s+=_j;
s+=F("=");
s+=portal.flot.read(_a[_j]);
s+=F(";\n");
_j++;
}
s+=F("$.plot(\"#flotplot\", [");
_j=0;
while (_j<3){
s+=F("d");
s+=_j;
if (_j!=2) s+=F(",");
_j++;
}
s+=F("]);})</script>\n;<div id='flotplot'></div>");
GP.SEND(s);
}
нет, не так. Нужен класс графика, то есть создаём график
GP_plot plot;
Конфигурируем, пишем туда
plot.write(blahblah);
И отправляем
GP.SEND(plot);
и SEND принимает SEND(GP_plot& plot);
И всё завязано на динамической памяти
это полностью иной подход. Я создаю буфер, из буфера будет выводится в график. То есть я в конструкторе просто передаю параемтры графика и номер буфера для построения, график должен сам строится, сам черз запрос получает данные из нужного буфера, (или из нескольких за 1 раз). конструктор просто сделает скрипт, остальное должен делать jquery. Я пока тестирую каким образом более гшраммотно строить эту хрень, перед тем, как делать финишный для построения графика.
не, это фигня) в самом портале не должно быть никаких буферов. Сделай код для визуала, я подом допилю бэкэнд
я веб-сериал тоже отдельно выношу, чтобы их можно было несколько штук сделать и вывести с кайфом
Я запутался, в самом портале буфера появляются только после portal.flot.start("ДлинаБуфера1,ДлинаБуфера2,....,ДлинаБуфераN"); Если сделать стоп, то они уходят в небытье. Вроде по феншую, Веб сериал и сейчас с небольшими изменениями можно несколько штук напилить, в этом есть смысл, согласен. Но то, как сделано сейчас, это очень классно, не могу понять зачем отдельно каждый график объявлять. Ведь по факту один и тот же буфер можно объявить 1 раз и выводить его хоть в 15 разных графиков в разных вариациях, делать зум, менять интервал, можно напилить интерфейс, подобный Заббиксу
ну вот нужно тебе на одной странице два графика вывести. Всё, приехали
"ДлинаБуфера1,ДлинаБуфера2,....,ДлинаБуфераN"
уууу нет, это по максимум нелогично и некрасиво. Объекты должны быть, и всё, не надо изобретать велосипеды)
ну вот нужно тебе на одной странице два графика вывести. Всё, приехали
не убедил, у меня это легко получится. Плюс все эти графики будут обновляться по ajax. и на несколько графиков можно будет запихать одну и ту же кривую... Допустим график температура - давление, тут же рядом график с той же температурой и мощностью нагревателя, при этом не будет уходить лишняя память, так бы пришлось температуру писать одновременно на 2-3 графика, а так только в один буфер
не, не поддерживаю такой кипиш. Не должно быть у портала внутри каких то составных буферов, всё должно быть отдельно. И лог тоже должен быть отдельным модулем. А память можно сэкономить другими подходами
я нумб в программировании, честно, я как бы сделал отдельных класс для работы с буферами (звучит прикольно), просто я его подцепляю к классу портала, так как хочу, чтобы при обработке события /flot_upd? без лишнего геммороя одной строкой отдавать данные для построения графика.
сделаю по красоте масимально)
опять несколько идей появилось, надо всё добавить(
я пока фигачу до результата, а там посмотрим, может мои идею можно будет переложить на иные алгоритмы. А тебе надо пока выкинуть из головы все идеи,и заняться ненавистными делами (документацией и примерами) Я вообще за графики взялся, чтобы хоть как то оправдать внедрение jquery
не, на доку пока нет времени, видос не успеваю доделать и дел семейных очень много гора)
Понимаешь, я хочу сделать так, чтобы джава сделала запрос G1X1Y2G2X2Y3, а портал в ответ дал строку, которая бы содержала данные для первой кривой(при этом х разделил на 10 а y на 100) и для второй кривоой (при этом x разделил на 100 а y на 1000), ява взяла данные и построили график. При это не обнуляя буфер, чтобы можно было и другие графики строить, сейчас допиливаю функцию чтения а в конструкторе минимум параметров (название осей и номера буферов кривых и всё)
пока не очень понял, главное чтобы это не стало графиком одного применения, котоырй сложно переделать под что то другое в случае чего
Ладно, поехали, класс буфера
class GPflot {
public:
/*
Хотел как проще для инициализации сделать, пришлось подключать строки, делаем portal.flot.start("100,20,50");
Эта строка запустит 2 буфера (на Х и на У), но так же запомнит начало и длинну каждого по отдельности
Скажем кому сколько надо, хочете 1 линию на 100 точек, или 10 линий на 50, нет ограничений, только ресурсы МК
*/
void start(String _str="20") {
if (_state) return;
_str += ',';
int _count=0;
for (int8_t _i=0;_i<_str.length();_i++) if (_str[_i]==',') _count++;
head = new int [_count];
BufLen = new int [_count];
pos = new int [_count];
pos[0]=0;
for (int8_t _i=0;_i<_count;_i++){
int _length=_str.substring(0,_str.indexOf(",")).toInt();
head[_i]=0;
BufLen[_i]=_length;
if (_i>0) pos[_i]=pos[_i-1]+_length;
size+=_length;
_str=_str.substring(_str.indexOf(",")+1);
}
buffer_x = new unsigned long [size]; //что то мне показалось, что по Х мало кто будет юзать отрицательные значения
buffer_y = new long [size];
for (int _i=0;_i<size;_i++) { //без этого очень всё плохо, мусор из памяти надо почистить
buffer_x[_i]=NULL;
buffer_y[_i]=NULL;
}
_state=true;
}
~GPflot() {
stop();
}
void stop() {
if (_state) {
delete [] buffer_x;
delete [] buffer_y;
delete [] head;
delete [] pos;
delete [] BufLen;
buffer_x = nullptr;
buffer_y = nullptr;
head = nullptr;
pos = nullptr;
BufLen = nullptr;
_state = false;
}
}
// запись в буфер (по кругу, не очищая буфер от значений, просто его зацикливаем)
// выбираем номер буыера и пихаем в него данные
void write(uint8_t num, unsigned long xn, long yn) {
if (_state){
if (head[num]<BufLen[num]){
buffer_x[head[num]+pos[num]]=xn;
buffer_y[head[num]+pos[num]]=yn;
head[num]++;
} else {
buffer_x[head[num]+pos[num]]=xn;
buffer_y[head[num]+pos[num]]=yn;
head[num]=0;
}
_available=true; //эта штука говорит о том, что была произведена запись после последнего считывания
}
}
//В реад передаём параметры для формирования правильного ответа (номер буфера, делители по x и по y)
//1GdelxXdelyY2GdelxXdelyY --- 1G1X2Y2G2X3Y
String read(String _str) {
String s;
s+="[";
uint8_t _count=0;
for (int8_t _i=0;_i<_str.length();_i++) if (_str[_i]=='G') _count++; //кол-во кривых
for (int8_t _i=0;_i<_count;_i++){ //извлекаем параметры
uint8_t num=_str.substring(0,_str.indexOf("G")).toInt(); //номер кривой
_str=_str.substring(_str.indexOf("G")+1); //избавляемся от лишнего
uint8_t delx=_str.substring(0,_str.indexOf("X")).toInt(); //делитель по Х
_str=_str.substring(_str.indexOf("X")+1); //избавляемся от лишнего
uint8_t dely=_str.substring(0,_str.indexOf("Y")).toInt(); //делитель по У
_str=_str.substring(_str.indexOf("Y")+1); //избавляемся от лишнего
double _delx=pow(10,delx); //кол-во знаков переводим в 10 в степени N
double _dely=pow(10,dely);
float _bufTemp_x, _bufTemp_y; //временные переменные
s +="[";
for (int _i=pos[num]+head[num];_i<(pos[num]+BufLen[num]);_i++) { //чтение по кругу, где то тут небольшой глюк,
_bufTemp_x=buffer_x[_i]/_delx; //позже найду
_bufTemp_y=buffer_y[_i]/_dely;
s+="[";
s+=_bufTemp_x;
s+=",";
s+=_bufTemp_y;
s+="],";
}
for (int _i=pos[num];_i<(pos[num]+head[num]);_i++) {
_bufTemp_x=buffer_x[_i]/_delx;
_bufTemp_y=buffer_y[_i]/_dely;
s+="[";
s+=_bufTemp_x;
s+=",";
s+=_bufTemp_y;
s+="],";
}
s[s.length()-1]=']';
if ( _i < _count-1) s+=",";
}
s+="]";
_available=false; //это лишнее - удалить
return s; //по итогу строка вида [[[x,y],[x,y],[],[]],[[],[],[],[],[],[],[],[]],[[],[],[]]]
}
bool available() { //лишнее, но это пока не точно
return (_available&&_state);
}
bool state() {
return _state;
}
private:
bool _available=false;
bool _state=false;
unsigned long* buffer_x = nullptr;
long* buffer_y = nullptr;
int* head = nullptr;
int* BufLen = nullptr;
int* pos = nullptr;
int size=0;
};
Теперь конструктор выглядит так (это не последняя версия, просто почти час ночи) В последней версии не будет передаваться портал, будет скрипт запроса, который сам в автомате будет получать данные, заставим яву поработать, пока просто тест
GP_FLOT("1G1X1Y2G1X2Y",portal);
кастом плот
void GP_FLOT(const String& strinit,GyverPortal& portal){
String s;
s.reserve(1000);
s+=F("<link href='/GP_flot.css' rel='stylesheet' type='text/css'>\n"
"<script language='javascript' src='/GP_jquery.js'></script>\n"
"<script language='javascript' src='/GP_flot.js'></script>\n"
"<script>\n$(function(){\n var data=");
s+=portal.flot.read(strinit);
s+=F("\n$.plot(\"#flotplot\", data);"
"})</script>\n<div id='flotplot'></div>");
GP.SEND(s);
}
Запуск трёх буферов по 25 точек в каждом
portal.flot.start("25,25,25");
portal.start();
Serial.println("Portal run");
while (portal.tick()){
static uint32_t tmr;
if (millis() - tmr > 1000) {
tmr = millis();
portal.flot.write(0,millis()/1000,random(1000));
portal.flot.write(1,millis()/1000,random(1000));
portal.flot.write(2,millis()/1000,random(1000));
Результат такой:
круто! Пока не осилю разобраться, сначала нужно ОТА от Дениса интегрировать