-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Графики JQuery #38
Comments
Все три типа графиков никто не будет юзать в одном проекте. На данный момент у меня переделана опять файловая система, и файлы графиков больше не дублируются несколько раз в папках |
Да я просто, скачал сегодня эту штуку, посмотрел каких там только графиков нет.... Доберусь до других проектов, посмотрю на графики. До сих пор ещё не попробовал |
А так добавим ессесн. Я их в принципе видел, это самые популярные веб графики |
Вообще мне понравилось как работает лог. То есть подключаем буфер и пишем в него данные, потом буфер выводим в лог. Может так же сделать, там где запускаем портал, делаем для для графика количество линий, количество точек по x,y... А в конструкторе просто объявляем график, указывая его дополнительные параметры. |
Может и так, это будет уже полноценный крупный модуль. И будут проблемы с типами данных, но они в целом решаемы |
Лолллл |
Не спешите смеяться раньше времени, сейчас немного код причешу, думаю моя затея будет по душе! |
Конечно по душе) просто графики выглядят как бык нассал) это чисто по точкам строится, без привязки к одной оси как времени? |
нет, это я строю таким макаром
x и y делаю рандомно, можно привязать к millis() |
Не, так не пойдет. Нужно делать отдельный класс графика, и дать возможность билдеру его выводить напрямую от объекта |
да я вроде так и делал 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);
} |
нет, не так. Нужен класс графика, то есть создаём график |
это полностью иной подход. Я создаю буфер, из буфера будет выводится в график. |
не, это фигня) в самом портале не должно быть никаких буферов. Сделай код для визуала, я подом допилю бэкэнд |
я веб-сериал тоже отдельно выношу, чтобы их можно было несколько штук сделать и вывести с кайфом |
Я запутался, в самом портале буфера появляются только после portal.flot.start("ДлинаБуфера1,ДлинаБуфера2,....,ДлинаБуфераN"); Если сделать стоп, то они уходят в небытье. |
ну вот нужно тебе на одной странице два графика вывести. Всё, приехали |
уууу нет, это по максимум нелогично и некрасиво. Объекты должны быть, и всё, не надо изобретать велосипеды) |
не убедил, у меня это легко получится. Плюс все эти графики будут обновляться по ajax. и на несколько графиков можно будет запихать одну и ту же кривую... Допустим график температура - давление, тут же рядом график с той же температурой и мощностью нагревателя, при этом не будет уходить лишняя память, так бы пришлось температуру писать одновременно на 2-3 графика, а так только в один буфер |
не, не поддерживаю такой кипиш. Не должно быть у портала внутри каких то составных буферов, всё должно быть отдельно. И лог тоже должен быть отдельным модулем. А память можно сэкономить другими подходами |
я нумб в программировании, честно, я как бы сделал отдельных класс для работы с буферами (звучит прикольно), просто я его подцепляю к классу портала, так как хочу, чтобы при обработке события /flot_upd? без лишнего геммороя одной строкой отдавать данные для построения графика. |
сделаю по красоте масимально) |
опять несколько идей появилось, надо всё добавить( |
я пока фигачу до результата, а там посмотрим, может мои идею можно будет переложить на иные алгоритмы. |
не, на доку пока нет времени, видос не успеваю доделать и дел семейных очень много гора) |
Понимаешь, я хочу сделать так, чтобы джава сделала запрос 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)); |
к этой штуке отдельная вики нужна) |
однако на версии cpp ардуино работает variadic void va(int num, ...) {
va_list valist;
va_start(valist, num); // initialize
for (int i = 0; i < num; i++) {
Serial.print(va_arg(valist, int)); // access
Serial.print(',');
}
va_end(valist); // clear
Serial.println();
}
void setup() {
Serial.begin(115200);
va(4, 2,3,4,5);
va(3, 5,10,15);
}
void loop() {
} |
Отличный код, то что надо! |
На самом деле, после игры с динамическим массивом чара, я в итоге поменял взгляд на буфера. Инициализация будет происходить одной циферкой, передавая количество линий. Буфер будет подключаться в случае необходимости. Можно будет в любой момент изменить размер буфера любой кривой. |
Пересмотрел подходы немного, скинул пару килобайт с библиотеки void loop() {
//Говорим что у нас будет три линии
myflot1.init(3);
//для первых двух линий делаем буфер, указываем кол-во точек в буфере и делители по x и по y
myflot1.setBuffer(1,360,100,100);
myflot1.setBuffer(2,36,1,100);
//Третий буфер передаём строкой (сделал в екселе просто запихал сюда)
myflot1.setData(3,"[1,0.841],[2,0.909],[3,0.141],[4,-0.757],[5,-0.959],[6,-0.279],[7,0.657],[8,0.989],[9,0.412],[10,-0.544],[11,-1],[12,-0.537],[13,0.42],[14,0.991],[15,0.65],[16,-0.288],[17,-0.961],[18,-0.751],[19,0.15],[2,0.909],[21,0.837],[22,-0.009],[23,-0.846],[24,-0.906],[25,-0.132],[26,0.763],[27,0.956],[28,0.271],[29,-0.664],[30,-0.988],[31,-0.404],[32,0.551],[33,1],[34,0.529]");
//Далее присваеваем имена линиям
myflot1.setLabelName(1,"sin");
myflot1.setLabelName(2,"cos");
myflot1.setLabelName(3,"rnd");
// Говорим где должна быть легенда, так же указываем сколько столютков в легенде
myflot1.setLegend("sw",3);
// Тут параметры сетки, тут не буду вдаваться в детали
myflot1.setGrid("shclhoah");
// Тут мы для каждой линии задаём оси, конкретно в этом варианте делаем три оси ОХ и 2 оси OY
myflot1.setLineOxAxis(1,1);
myflot1.setLineOxAxis(2,2);
myflot1.setLineOxAxis(3,3);
myflot1.setLineOyAxis(1,1);
myflot1.setLineOyAxis(2,1);
myflot1.setLineOyAxis(3,2);
// Тут говорим что первая линия будет показана как линия с заполнением
myflot1.setLineType(1,"LF");
// на второй линии показать точки
myflot1.setLineType(2,"LP");
// третью линию делать в режиме BARS
myflot1.setLineType(3,"B");
Здесь мы просто говорим куда распихать оси, ось 1и2 по Y пихнуть на лево и право, 2 оси по Х поставить снизу, одну на верх
myflot1.setYaxes(1,"left");
myflot1.setYaxes(2,"right");
myflot1.setXaxes(1,"bottom");
myflot1.setXaxes(2,"bottom");
myflot1.setXaxes(3,"top");
while (portal.tick()){
static uint32_t tmr;
static int xx=0;
if (millis() - tmr > 100) {
tmr = millis();
float xxf=xx;
//Тут пихаем данные в буфер
myflot1.setDataFloat(1,xxf,sin(xxf*3.14/180));
if (xx%10==0) myflot1.setDataFloat(2,xx,cos(xxf*3.14/180));
xx++;
}
}
} Надо понимать, что это нереальный график, и в реальности таких графиков никто делать не будет. ну и нваерное выкину код библиотеки, я же в принципе восприимчив к критике, но реально уже запарился, код надо ещё немного прибрать, распихать функции по порядку и отступы сделать так, чтобы получше воспринималось. У меня кроме ардуино IDE только NOTEPAD++, в принципе именно он меня и спасает Планирую ещё потратить немного времени на все защиты от дурака, чтобы не класть контроллер в panic, ну и приступить написанию чисто ява скриптов для обновления и иных эффектов. Код позволят в принципе безболезнено добавлять вставки всех скриптов на данный скелет. |
Для обсуждения и критики!
Ориентировочно подойду к доработке данного класса через пару недель. |
Блин, это всё нужно колупать самому? В моих графиках это было по умолчанию практически |
Ну тут борьба за память и за автономность. Стоит оно того? Наверное если использовать МК в местах, где вместо Интернета 4G горит E (в смысле за МКАД), то наверное стоит. Собрать какой то конкретный график из flot очень просто, собрать класс для конструирования любого вида графика, пытаясь сохранить максимум возможностей сего инструмента - гораздо сложнее. |
Ну условно мой Аякс плот весит 300кб и работает из оффлайна. Твой со всеми нужными библами сколько будет весить? |
для всех графиков вместе с библой jquery по максимуму в районе 200 Кб |
Вчерашний твой инструмент для записи в файл мне не даёт покоя. Основное в графиках - это вывод результатов.
|
Ну вот, оказывается на гитхабе flot немного шире, чем при загрузке с сайта, и достаточно новее, однако есть свои минусы. Скачал оттуда, файлы js весят 405 кБ, для комфортной работы со временем и без грабель (там используются файлы Олсона с таймзонами) надо ещё дополнительно 750 кБ... ИТОГО - 1,15МБ Изучил алгоритм действующих графиков, без проблем реализую построение графика через указатель на массив и его длину, при этом функции добавления данных в массив будут штатными. Из проблем: Мне на данном этапе (для одной из фишек класса) надо понять как дописывать в файл данные в бинарном формате, то есть каким образом в файл дописывать данные в формате x,y, uint32_t таким образом, чтобы потом их можно было считать. Нужен сам алгоритм, писать будет с++, а вот вычитывать должен скрипт явы. Как я понимаю, надо x,y преобразовать в 4байта + 4 бйайта и писать их разом в файл. При этом при инициализации класса, в случае если класс настроен на запись в файл, то необходимо проверить, что размер файла кратен 8 (на случай отвала питания и прочего). Ява же должна будет вычитывать из файла блоками по 8 байт, разделять их на x,y, делать нужные преобразования согласно настроек класса, формировать массивы. Далее просто массивы кидаем на график и всё С realtime не вижу проблем (в примерах всё просто), так что оставляю это на потом. Медленно и верно продолжаю мучать свой мозг, эти графики скорее нужны мне, для повышения гибкости ума и набиранию опыта, но по итогу можно получить (не быстро) достойный формат полностью офлайн графиков размером не более 450 кБ (с библой jquery) с поддержкой записи в файл, буфер, прогмем, с возможностью реалтайм, muliaxis, multiline, масштабированием и прочим... С поддержкой трёх разных видов линий. |
А таймзоны зачем нужны? Юзер может сам указать свой gmt Писать в файл - через запятую на новой строке. Прочитать можно будет как readLine и split(,) |
вот без этих файлов у меня не получилось заставить flot работать через указание TZ, но это было ранее , сейчас буду проверять... И да, про запись в файл, как то не экономично получается, 4 байта может закодировать uint32_t, а так что я получу?, я вспоминаю твой инструмент по записи структуры в файл, и он мне нравится, я код смотрел, но ничего не понял:) но там правильный подход. Могу конечно начать с простого и сделать как ты говоришь, но в идеале надо будет стремится к экономии места и записи. У меня потихоньку начинает появляться время, постараюсь провести его с пользой для своего ума. |
Писать в файл бинарные данные в этом случае не имеет смысла, всегда есть сценарий "скачать файл и закинуть в ексель", или просто скачать человеко-читаемые/редактируемые данные. В этом плане я бы даже пожалуй выбрал формат CSV - это будет супер удобно для всего. Сжатие по моему варианту весьма коварно, оно увеличивает размер бинарных данных аж в 4/3 раза. А как оно запаковано - разбираться бессмысленно. Это обычное base64 кодирование, можно разобрать на стороне браузера какими нибудь средствами js. Но в js у тебя нет структур, байтов и юинт32, также ты не знаешь как компилятор есп упакует структуру, потому что напомню что поля должны быть кратны 4 байтам, то есть байт+байт+юинт32 есп запишет с добавлением двух пустых байтов после первых двух. Короче это не имеет смысла. |
Понял, принял. Делаю csv, свою задумку оставлю не потом. Я хотел в файл писать сперва x длинной 4 байта, потом y длинной 4 байта и прям один за другим. И Явой так же вычитывать, блоками по 8 байт... Это было бы максимально эффективно в сфере использования памяти. |
Бессмысленно. Уж куда лучше добавить один байт переноса строки, чтобы читать данные строками. Это же позволит использовать разное количество данных в строке с автоматическим определением количества данных, а в менеджере файлов есп вообще должны быть инструменты построчного чтения и дописывания, что тоже удобно |
С таймзоной разобрался, если оставить файл размером 942 байта, то в принципе всё пашет в виде timezone: "Etc/GMT+X" |
200 КБ на все возможные фичи, которые нужно просто настроить и они будут работать?) Звучит вкусно. А jquery там интересно зачем нужен? |
Ну я просто посчитал, жиквери всё равно уже есть, так что остаётся на графики 150 кб. Звучит очень вкусно. Но надо пилить вики, я на форуме как первая линия хелпдеска по твоей либи, и в вики не послать, и совесть не позволяет мимо проходить. |
Какие чаще всего вопросы? |
разные, есть и такие, на которые я даже не знаю как отвечать https://community.alexgyver.ru/threads/gyverportal.6632/post-129698, так как сам не знаю почему такое происходит. В основном подходы не всегда верные выбираются, надо прям на примерах уроки пилить, лучше видео, люди мало смотрят примеры, либо не могут найти нужные... Некоторые хотят сделать по своему, хотя можно просто поменять подход к решению задачи, с некоторыми у меня прям личные переписки на форумах. То файлы не могут подцепить, то ещё что нить, проблемные моменты я тут озвучиваю, пока косяков в алгоритмах работы библиотеки не наблюдаю... Но наверное обновление данных и обработчик событий.... там иногда затыки |
Интересно... Возможно нужно делать urlencode. Попробую |
Там человек пишет, что у него и при отправке в serial не доходит плюс. Но он потерялся (чел потерялся, я его просил посмотреть через инструменты разработчкиа что броузер отправляет на мк), надо проверять самим, а я не хочу. То есть теряется где то в getString |
Вот я и пишу - скорее всего нужен urlencode. Потому что плюс в декоде это пробел, что у него и происходит |
Я уже понял, но честно не помню чтобы подобные проблемы были при post запросах и связки lamp. |
Судя по всему портал набирает обороты, и это если учесть то, что ты про него упомянул только в телеге... Знаешь, ты как тот человек из мультика - делай добро и бросай его в воду... Респект! |
Не, три раза в видео было, просто не очень целевая аудитория. Надо на канал с уроками сделать цикл уроков по нему, но сначала база есп |
Как пойдут поделки на есп, так будет аудитория.... Это всё лирика, библиотека - супер. |
Раз в новый портал внедряется возможность юзать jquery, решил исследовать Инет на предмет графиков с использованием данной библиотеки.
http://www.flotcharts.org/downloads/
Вот это мне понравилось, даже сейчас скажу чем именно понравилось:
Просто как вариант, сам у себя пока не использую графики в проекте, но а вдруг эта идея тебе понравится.
The text was updated successfully, but these errors were encountered: