Apache+php--->browser+js+svg

Тема в разделе "Raspberry Pi", создана пользователем Igor68, 4 июл 2024 в 13:46.

  1. Igor68

    Igor68 Гуру

    Доброго времени суток!
    PS: Пишу сие от жары, что устал немного, ну... и в надежде что это кому-то поможет. Сам через такое прошел не так давно. Всё рассматриваемое реализация того что описано:
    https://forum.amperka.ru/threads/Разговоры-на-технические-темы.22016/page-12#post-314348
    А именно построение графиков в окне браузера, отображение данных и прочее.

    ШАГ 1:
    Начинается всё с получения данных от сервера... WEB сервера конечно. Точнее Вашего локального WEB сервера на устройстве (предположительно МАЛИНЫ, но можно и другого). Предполагается что на этом устройстве крутится ещё что-то полезное, данные которого надо отображать в браузере.
    Сначала получение данных просто обращаясь к скрипту на этом сервере из браузера. А почему не напрямую, а через скрипт? Да потому что скрипт, в моём случае PHP, но можно Питон и прочее может выполнять что-то еще - к примеру обращаться к базе данных например MySQL.
    Обратившись к файлу MyPHP.php из распакованного архива:
    DataSVGtest.zip - это архив всей страницы WEB сервера (в моём случае Apache).
    Вы должны получить данные в формате JSON в окне браузера.
    Это содержимое файла "data/abpupowerauto.json" - это набор данных, которые надо отобразить:
    -- массив "ДАТА и ВРЕМЯ" в формате UTC
    -- массив "НАПРЯЖЕНИЕ"
    -- массив "ЧАСТОТА"
    эти параметры приведены как пример от реальных измерений. Следует отметить, что данные в реальности постоянно перезаписываются и накопитель в виде NAND в связи с недолговечностью непригоден. В нашем случае это просто статический пример пример.

    PS: Простите, но описано всё будет пошагово.
     

    Вложения:

    • DataSVGtest.zip
      Размер файла:
      4,8 КБ
      Просмотров:
      13
    Последнее редактирование: 4 июл 2024 в 14:54
  2. Igor68

    Igor68 Гуру

    ШАГ2:
    Теперь надо, чтобы загружаемая страница отображала область SVG:
    [​IMG]
    И загружала данные самостоятельно с интервалом времени. Это можно проконтролировать с помощью браузера (у меня Firefox)
    МЕНЮ: Инструменты-->Инструменты браузера-->Инструменты вэб-разработчика. в Опции "Отладчик" в файле "index.js" в функции:
    Код (Javascript):
    //Запросы серверу
    var dbI;
    function LoadIndex() {
        var str;
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.onreadystatechange = function () {
        if(xmlHttp.readyState == 4) {
            if(xmlHttp.status == 200) {
                str = xmlHttp.responseText;
                //document.getElementById("test").innerHTML = str;
                dbI = eval('(' + str +')');
                ParseIndex();
                }
            }
        }
        xmlHttp.open("GET", "MyPHP.php?dtime=" + new Date().getTime(), true);
        xmlHttp.send();
    }
    Сделать точку останова в строке с содержимым ParseIndex(); и при остановке навести курсор
    на значение dbI в предыдущей строке.
    должны быть определены:
    Код (Text):
    F220: (800)  [...]
    U220: (800)  [...]
    dtime: (800)  [...]
    Значит мы получаем с интервалом:
    Код (Javascript):
    const tloop = 1000;    //таймаут ms цикла данных
    данные от нашего сервера:
    --частота 800 значений
    --напряжение 800 значений
    --дата и время 800 значений
    Учтите, что ваша программа (если не этот пример) на сервере должна перезаписывать/изменять массивы в файле "abpupowerauto.json". Это только пример.

    Архив страницы на сервере:
    DataSVGtest.zip
     

    Вложения:

  3. Igor68

    Igor68 Гуру

    Итак данные принимаем, заготовлена ВЭБ страница.
    ШАГ3:
    Приступаем к созданию координатной сетки, если нужна:
    [​IMG]
    Следует отметить, что для работы были описаны ряд функций в отдельный файл - язык не поворачивается назвать библиотекой.
    Файл "graphSVG.js" содержит функции для работы:
    -- Инициализация "холста"
    -- Фиксация шаблона и работа с ним
    -- Рисование ЛИНИИ и ПРЯМОУГОЛЬНИКА на холсте
    -- Вывод текстовой строки на холст
    -- Получение координат курсора мыши на холсте
    Можно конечно всё это делать и своими функциями, но уж больно скучно.
    Следует иметь в виду что в данном примере реализовано два цикла:
    --Цикл данных (получение от сервера):
    Код (Javascript):
    //цикл данных
    function MyLoop() {
        LoadIndex();
         setTimeout(MyLoop, tloop);
    }
    --Цикл графики:
    Код (Javascript):
    //цикл графики
    function LoopGraph() {
        ClearGraphSVG(); //обновляем холст из шаблона, а не рисуем каждый раз
       
        setTimeout(LoopGraph, tgraph);
    }
    Но стартовая функция не только запускает эти циклы, и инициализирует параметры холста:
    Код (Javascript):
    unction MyStart() {
        //
        InitGrarhSVG("MySVG", Xmax, Ymax); //инициализируем холст
        GrawGrid();    //рисуем сетку
        SetPatternSVG(); //принимаем весь холст с сеткой как шаблон
        //активация "циклов"
        MyLoop();
        LoopGraph();
    }
     
    Архив с примером:
    DataSVGtest.zip
     

    Вложения:

  4. Igor68

    Igor68 Гуру

    Ну теперь всё готово для отображения данных. Приступим...
    ШАГ4:
    На текущем шаге определяем масштабы параметров ЧАСТОТА и НАПРЯЖЕНИЕ, нанесение значений на сетку,
    отображение параметров в виде графиков из массивов, отображение текущих значений в левом верхнем углу холста.
    Код (Javascript):
    //цикл графики
    function LoopGraph() {
        ClearGraphSVG(); //обновляем холст из шаблона, а не рисуем каждый раз
        //
        if(DataFlag == true) {
            var cnt = 0;
            var sx = 1;
            var x1 = 0;
            //график (из отрезков) на холст
            while(cnt < 799) {
                var x2 = x1 + sx;
                //в левом верхнем углу последнее измерение - реального времени
                if(cnt == 0) {
                    DrawText("rU220t", 5, 15, '12px', "rgb(255,0,0)", U220[cnt] + "V");
                }
                DrawLine("U220" + cnt, x1, 201 - ((U220[cnt] - 230) * GU220s), x2, 201 - ((U220[cnt + 1] - 230) * GU220s), "1px", "rgb(255,0,0)" );
                x1 = x2;
                cnt++;
            }
            var x1 = 0;
            cnt = 0;
            //график (из отрезков) на холст
            while(cnt < 799) {
                var x2 = x1 + sx;
                //в левом верхнем углу последнее измерение - реального времени
                if(cnt == 0) {
                    DrawText("rF220t", 5, 27, '12px', "rgb(0,255,0)", F220[cnt] + "Hz");
                }
                DrawLine("F220" + cnt, x1, 201 - ((F220[cnt] - 50) * GF220s), x2, 201 - ((F220[cnt + 1] - 50) * GF220s), "1px", "rgb(0,255,0)" );
                x1 = x2;
                cnt++;
            }
            //параметры (масштаб) на сетке
            cnt = 1;
            while(cnt < 4) {
                var uf = Math.round((startscale + (cnt * scale)) * Math.pow(10,2)) / Math.pow(10,2);
                DrawText("U220t" + cnt, 105, 401 - (cnt * 100) - 5, '12px', "rgb(255,0,0)", uf + "V");
                var df = Math.round((fstartscale + (cnt * fscale)) * Math.pow(10,2)) / Math.pow(10,2);
                DrawText("F220t" + cnt, 705, 401 - (cnt * 100) - 5, '12px', "rgb(0,255,0)", df + "Hz");
                cnt++;
            }
            var uf = Math.round((startscale + (cnt * scale)) * Math.pow(10,2)) / Math.pow(10,2);
            DrawText("U220t" + cnt, 105, 401 - (cnt * 100) + 15, '12px', "rgb(255,0,0)", uf + "V");
            var df = Math.round((fstartscale + (cnt * fscale)) * Math.pow(10,2)) / Math.pow(10,2);
            DrawText("F220t" + cnt, 705, 401 - (cnt * 100) + 15, '12px', "rgb(0,255,0)", df + "Hz");
            //ДАТА и ВРЕМЯ на сетке
            cnt = 0;
            while(cnt < 8) {
                var Dstr = timeConverter(dtime[cnt * 100] * 1000, 255);
                var Tstr = timeConverter(dtime[cnt * 100] * 1000, 0);
                DrawText("Date" + cnt, (cnt * 100) + 5, 401 - 5, '12px', "white", Dstr);
                DrawText("Time" + cnt, (cnt * 100) + 5, 401 - 17, '12px', "white", Tstr);
                cnt++;
            }
        }
     
        setTimeout(LoopGraph, tgraph);
    }
    А парсинг в цикле данных - определение масштаба шкалы и т.п.
    Код (Javascript):
    function ParseIndex() {
        var cnt = 0;
        U220max = 0;
        U220min = 999;
        F220max = 0;
        F220min = 999;
        //определяем максимумы и минимумы параметров и заполнение массивов
        while(cnt < 800) {
            U220[cnt] = parseFloat(dbI.U220[cnt]);
            if(U220max < U220[cnt]) U220max = U220[cnt];
            if(U220min > U220[cnt]) U220min = U220[cnt];
            F220[cnt] = parseFloat(dbI.F220[cnt]);
            if(F220max < F220[cnt]) F220max = F220[cnt];
            if(F220min > F220[cnt]) F220min = F220[cnt];
            dtime[cnt] = parseInt(dbI.dtime[cnt], 10);
            cnt++;
        }
        //напряжение - масштаб шкалы
        if((Math.abs(U220max - 230) < 4) && (Math.abs(U220min - 230) < 4)) {
            GU220s = 50;    //200px / 4v
            scale = 2;
            startscale = 226;
        } else    if((Math.abs(U220max - 230) < 10) && (Math.abs(U220min - 230) < 10)) {
            GU220s = 20;    //200px / 10v
            scale = 5;
            startscale = 220;
        } else if((Math.abs(U220max - 230) < 20) && (Math.abs(U220min - 230) < 20)) {
            GU220s = 10;    //200px / 20v
            scale = 10;
            startscale = 210;
        } else if((Math.abs(U220max - 230) < 40) && (Math.abs(U220min - 230) < 40)) {
            GU220s = 5;        //200px / 40v
            scale = 20;
            startscale = 190;
        } else if((Math.abs(U220max - 230) < 100) && (Math.abs(U220min - 230) < 100)) {
            GU220s = 2;        //200px / 100v
            scale = 50;
            startscale = 130;
        } else if((Math.abs(U220max - 230) < 200) && (Math.abs(U220min - 230) < 200)) {
            GU220s = 1;        //200px / 200v
            scale = 100;
            startscale = 30;
        } /*else if((Math.abs(U220max - 230) < 230) && (Math.abs(U220min - 230) < 230)) {
            GU220s = 1;
            scale = 115;
            startscale = 0;
        }*/

        //частота - масштаб шкалы
        if((Math.abs(F220max - 50) < 0.01) && (Math.abs(F220min - 50) < 0.01)) {
            GF220s = 10000;
            fscale = 0.01;
            fstartscale = 49.98;
        } else if((Math.abs(F220max - 50) < 0.1) && (Math.abs(F220min - 50) < 0.1)) {
            GF220s = 1000;
            fscale = 0.1;
            fstartscale = 49.8;
        } else if ((Math.abs(F220max - 50) < 2) && (Math.abs(F220min - 50) < 2)) {
            GF220s = 100; // 200px / 2Hz
            fscale = 1;
            fstartscale = 48; //49.8;
        } else if ((Math.abs(F220max - 50) < 5) && (Math.abs(F220min - 50) < 5)) {
            GF220s = 40; //200px / 5Hz
            fscale = 2.5;
            fstartscale = 45;
        }   else { //if ((Math.abs(F220max - 50) < 10) && (Math.abs(F220min - 50) < 10)) {
            GF220s = 20; //200px / 10Hz
            fscale = 10;
            fstartscale = 30;
        }
        //
        DataFlag = true;
    }
    [​IMG]
    Архив:
    DataSVGtest.zip

    PS: А вот определение параметров по маркеру, по координатам курсора на холсте, надо или нет - не знаю.
     

    Вложения:

  5. Igor68

    Igor68 Гуру

    ШАГ5:
    Скриншот сделать не мог, а фото с экрана что-то с чем-то. Когда наводится курсор мыши на полотно появляется на полотне окошко с данными и маркер (вертикальная линия) так же как тут:
    https://forum.amperka.ru/threads/Разговоры-на-технические-темы.22016/page-12#post-314348
    Собственно архив:
    DataSVGtest.zip


    Ну вроде всё.

    PS: Основной смысл в неиспользовании программ на стороне пользователя - только браузер.
    Если кто испытал, будьте добры сообщить что за браузер и каков результат. У меня Firefox с ОС Didian. Я это к тому, что у меня получалось на разных машинах иметь разные результаты отображений. Правда к SVG это не относилось, но всё же!
    Спасибо!
     

    Вложения:

    • DataSVGtest.zip
      Размер файла:
      12,7 КБ
      Просмотров:
      13
    Последнее редактирование: 5 июл 2024 в 11:34
  6. Igor68

    Igor68 Гуру

    Вот с танцами с бубном сделал скриншот:
    [​IMG]
    Дело в том, что уходом курсора из области холста макер и окно с данными исчезают. Курсор опять не отобразился на скриншоте.

    PS: Ребята скажите а у Вас сработало. Мне интересно про разные браузеры. У меня Firefox 115.12.0esr (64-разрядный) и ОС 5.10.0-30-amd64 #1 SMP Debian 5.10.218-1 (2024-06-01) x86_64 GNU/Linux
    Спасибо!
     

    Вложения:

    Последнее редактирование: 6 июл 2024 в 19:12