Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Русский
  3. ioBroker
  4. Скрипты
  5. ioBroker скрипты
  6. Передача показаний приборов учёта на web-сайт

NEWS

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    16
    1
    1.2k

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    740

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.0k

Передача показаний приборов учёта на web-сайт

Geplant Angeheftet Gesperrt Verschoben ioBroker скрипты
передача показаний счётчики
1 Beiträge 1 Kommentatoren 687 Aufrufe
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • A Offline
    A Offline
    andrey99986
    schrieb am zuletzt editiert von andrey99986
    #1

    Задача : передавать данные по приборам учёта на сайты УК.

    Условие: на web-сайте не должно быть капчи.

    Решение:

    Установить chromium браузер. Chromium для debian 10 ставится командой:
    "apt-get install chromium chromium-l10n".

    В свойства драйвера javascript дописываем библиотеку "puppeteer".

    Алгоритм навигации и заполнения:

    Для навигации по сайту используем селекторы.
    Приоритет при навигации по сайту с помощью библиотеки puppeteer:

    1. Если элемент страницы содержит id, например 'id=sendCountersValues', используем его. Самый лучший вариант. При копипасте через десктопный браузер селектор будет выглядеть так: '#sendCountersValues'. Однако некоторые id - автогенерируемые, необходимо убедиться что он не меняется в новой сессии браузера или при новой передачи данных.
    2. Через копипаст селектора как показано на картинках step1_selector.png, step2_selector.png. Главное чтобы скрипт при работе с таким селектором не выдавал ошибок. Селектор будет например таким: '#authorization_form > div:nth-child(2) > div > input'.
    3. По атрибуту 'name='. Селектор будет например таким: 'input[name=login]'. Возможная проблема - когда несколько данных имеют одинаковый 'name='. Этот случай рассмотрен ниже.
    4. По классу, например элемент имеет класс 'btn-lg'. Селектор будет тогда таким: '.btn-lg'. Уникальность так же не гарантирована, в этом случае подход такой же как в п. 3.
    5. Навигация курсором мыши или клавиатурой (Tab). Тупо, но работает когда по другому не получается.

    Внимание!
    После каждого ошибочного запуска скрипта в памяти остаётся процесс "chromium". Проверка: " ps aux|grep chromium"
    Рекомендую убивать процессы командой "killall chromium"
    Иначе вся оперативная память забъётся и система будет тормозить и глючить до перезагрузки.

    Скрипт с комментариями:

    const puppeteer = require('puppeteer');
    var util = require('util')
    //Запускаем раз в месяц 16 числа в 8:40
    schedule("40 8 16 * *", function () {
        send_data();
    
    }); //schedule end
    
    
    async function send_data() {
    //Присвоение переменным скрипта данных приборов учёта
    const Bath_cold = getState('modbus.0.holdingRegisters.12328_Bathroom_stat_cold_water').val/100;
    const Bath_warm =  getState('modbus.0.holdingRegisters.12330_Bathroom_stat_warm_water').val/100 + 0.006;
    const Kitchen_cold = getState('modbus.0.holdingRegisters.12324_Kitchen_stat_cold_water').val/100;
    const Kitchen_warm =  getState('modbus.0.holdingRegisters.12326_Kitchen_stat_warm_water').val/100;
    
    //log('Bath_cold='+Bath_cold+', Bath_warm='+Bath_warm);
    //log('Kitchen_cold='+Kitchen_cold+', Kitchen_warm='+Kitchen_warm);
    
    //Проверка на допустимый диапазон данных
    if (Bath_cold >1 && Bath_cold <100000 && Bath_warm>1 && Bath_warm<100000  && Kitchen_cold >1 && Kitchen_cold <100000 && Kitchen_warm>1 && Kitchen_warm<100000)
    {
    
    
      const browser = await puppeteer.launch({
      //указываем путь к chromium браузеру.
      executablePath: '/usr/bin/chromium',
      //разрешение с которым будет работать chromium. Должно быть достаточным для отображения всей страницы, с которыми будет работать chromium. Увеличить при необходимости. Не имеет отношение к разрешению экрана.
      'defaultViewport' : { 'width' : 1920, 'height' : 1080 }
    });
      const page = await browser.newPage();
     //подключаем функцию отображения указателя мыши (может понадобиться в редких случаях) 
     await installMouseHelper(page);
      //Указываем главную страницу сайта
      await page.goto('https://lk.rkcgkh.ru/', { waitUntil: 'networkidle0' });
      
     //Смотрим картинку step1_selector.jpg, копипастим селектор. Команда на ожидание появление селектора.  
      await page.waitForSelector('#authorization_form > div:nth-child(2) > div > input');
     //Другой вариант - ждём появления элемента с заданными атрибутами. 
     await page.waitFor('input[name=login]');
    
     //Указываем свой login и пароль 
      await page.$eval('input[name=login]', el => el.value = 'MYEAMAIL@yandex.ru');
      await page.$eval('input[name=password]', el => el.value = 'MYPASSWORD');
      
    //Селектор для кнопки можно определить несколькими способами: скопипастить - см. step2_selector.jpg
     //const selector1 = "#authorization_form > div:nth-child(4) > div.col-auto > button";
     //или определить так.
     const selector1_alt = ('button[type=submit]');
     //ждём когда селектор кнопки загрузится
      await page.waitFor(selector1_alt);
      //Здесь происходит клик по кнопке
      await page.click(selector1_alt);
      //Сохраняем картинку чтобы увидеть что происходит. Это момент сразу после клика поэтому страница будет такая же как перед кликом. Чтобы увидеть результат клика надо принудительно задать ожидание(ненадёжно) или ожидать загрузки селектора новой страницы.
      await page.screenshot({path: '/tmp/screen0.png'});
      //Определяем селектор - пункт меню "Показания" . Картинки нет, но подход полностью аналогичен предыдущему клику. 
      const selector2 = "#stack-sidebar > ul > li:nth-child(3) > a";
    //Ожидаем загрузки селектора для подтверждения открытия нового содержимого.
     await page.waitFor(selector2);
     //Вот здесь мы только увидим новую страницу после клика.
      await page.screenshot({path: '/tmp/screen1.png'});
     //Клик на пункте "Показания"
      await page.click(selector2);
    
     // Определяем селектор - блок в котором содержатся поля ввода данных. Это может быть любой вышестоящий блок с наличием идентификатора (id = "... ") или селекторы полей ввода.
      const selector3 = '#sendCountersValues';
    //Ожидаем загрузки селектора для подтверждения открытия нового содержимого.
      await page.waitFor(selector3);
    //Сохраняем скриншот для целей отладки. Здесь будут пустые поля
      await page.screenshot({path: '/tmp/screen2.png'});
    
    //На картинке step3.png смотрим атрибуты полей ввода по которым будет определяться селектор.
    // Копипаст селектора в данном случае  не сработал, возможно из-за бага в библиотеке при экранировании квадратных кавычек "[", "]" 
    
    //Вводим данные
     await page.$eval('input[name="counters[139786_0][value]"]', (el, var_KC) => el.value = var_KC,Kitchen_cold);
     await page.$eval('input[name="counters[139787_0][value]"]', (el, var_BC) => el.value = var_BC,Bath_cold);
     await page.$eval('input[name="counters[139788_0][value]"]', (el, var_KW) => el.value = var_KW,Kitchen_warm);
     await page.$eval('input[name="counters[139789_0][value]"]', (el, var_BW) => el.value = var_BW,Bath_warm);
    //Здесь картинка уже будет содержать данные, так как функция ввода с подтверждением ввода. 
    await page.screenshot({path: '/tmp/screen3.png'});
    
    //Создаём клик на кнопку "Передать", см step4.png, копипастим селектор. 
     const selector4= '#sendCountersValues > div.row.row-widget-next.row-submit > div > input';
    //Ожидаем загрузки селектора
     await page.waitFor(selector4);
    //Клик на кнопке "Передать"
     await page.click(selector4);
    //Ждём 2 секунды, а лучше сделать ожидание селектора новой страницы.
     await page.waitForTimeout(2000);
    //Здесь будет скриншот об успешном приёме данных. 
     await page.screenshot({path: '/tmp/screen4.png'});
    
      await browser.close();
    
      sendTo('telegram.0', '/tmp/screen4.png', function (res) { 
                        log('Sent to telegram ' + res + ' users'); 
                      });
    
    }
    }
    
    
    
    
    async function installMouseHelper(page) {
      await page.evaluateOnNewDocument(() => {
        // Install mouse helper only for top-level frame.
        if (window !== window.parent)
          return;
        window.addEventListener('DOMContentLoaded', () => {
          const box = document.createElement('puppeteer-mouse-pointer');
          const styleElement = document.createElement('style');
          styleElement.innerHTML = `
            puppeteer-mouse-pointer {
              pointer-events: none;
              position: absolute;
              top: 0;
              z-index: 10000;
              left: 0;
              width: 20px;
              height: 20px;
              background: rgba(0,0,0,.4);
              border: 1px solid white;
              border-radius: 10px;
              margin: -10px 0 0 -10px;
              padding: 0;
              transition: background .2s, border-radius .2s, border-color .2s;
            }
            puppeteer-mouse-pointer.button-1 {
              transition: none;
              background: rgba(0,0,0,0.9);
            }
            puppeteer-mouse-pointer.button-2 {
              transition: none;
              border-color: rgba(0,0,255,0.9);
            }
            puppeteer-mouse-pointer.button-3 {
              transition: none;
              border-radius: 4px;
            }
            puppeteer-mouse-pointer.button-4 {
              transition: none;
              border-color: rgba(255,0,0,0.9);
            }
            puppeteer-mouse-pointer.button-5 {
              transition: none;
              border-color: rgba(0,255,0,0.9);
            }
          `;
          document.head.appendChild(styleElement);
          document.body.appendChild(box);
          document.addEventListener('mousemove', event => {
            box.style.left = event.pageX + 'px';
            box.style.top = event.pageY + 'px';
            updateButtons(event.buttons);
          }, true);
          document.addEventListener('mousedown', event => {
            updateButtons(event.buttons);
            box.classList.add('button-' + event.which);
          }, true);
          document.addEventListener('mouseup', event => {
            updateButtons(event.buttons);
            box.classList.remove('button-' + event.which);
          }, true);
          function updateButtons(buttons) {
            for (let i = 0; i < 5; i++)
              box.classList.toggle('button-' + i, buttons & (1 << i));
          }
        }, false);
      });
    };
    

    Рассмотрим вариант когда элемент не уникален.
    В моём случае это была таблица с полями ввода, которая через селекторы никак не хотела работать.
    Пример на картинке step5.png.
    Решение следующее:

    const inputs = await page.$$('input[type=text]');
    await inputs[0].type(String(T1));
    await inputs[1].type(String(T2));
    

    Так как у всех элементов input есть общий атрибут "type=text" - загоняем их в массив, и обращаемся к элементам массива.

    Другой проблемный вариант кнопка на картинке step6.png , селектор через копипаст не работает.
    Решение - использовать class элемента :

    const button = await page.$('.btn-lg');
    await button.click();
    

    И самый плохой вариант, когда через селекторы не получается. Здесь уже нужна функция installMouseHelper, которую я нашёл на просторах интернета.
    Просто позиционируем курсор (небольшой серый кружок) на нужный элемент и кликаем - картинка step7.png:

    await page.mouse.move(600,820);
    await page.mouse.click(600,820);
    

    Кроме того, можно с помощью TAB-ов выбирать нужное поле. Просто вызываете нажатие TAB, сохраняете картинку и смотрите, какое поле подсвечено.

    await page.keyboard.press("Tab");
    await page.keyboard.press("Tab");
    await page.keyboard.press("Tab");
    await page.keyboard.type(String(T2));
    

    API библиотеки : puppeteer

    step1_selector.png step1_selector.png
    step2_selector.png step2_selector.png
    step3.png step3.png
    step4.png step4.png
    step5.png step5.png
    step6.png step6.png
    step7.png step7.png

    1 Antwort Letzte Antwort
    0
    Antworten
    • In einem neuen Thema antworten
    Anmelden zum Antworten
    • Älteste zuerst
    • Neuste zuerst
    • Meiste Stimmen


    Support us

    ioBroker
    Community Adapters
    Donate

    628

    Online

    32.6k

    Benutzer

    82.0k

    Themen

    1.3m

    Beiträge
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
    ioBroker Community 2014-2025
    logo
    • Anmelden

    • Du hast noch kein Konto? Registrieren

    • Anmelden oder registrieren, um zu suchen
    • Erster Beitrag
      Letzter Beitrag
    0
    • Home
    • Aktuell
    • Tags
    • Ungelesen 0
    • Kategorien
    • Unreplied
    • Beliebt
    • GitHub
    • Docu
    • Hilfe