Сниппеты



  • Сниппеты - это небольшие фрагменты кода, пригодные для повторного использования.

    В системе intraHouse можно использовать сниппеты для получения значений устройств без привязки к каналам плагинов. То есть это легковесная замена плагина.

    Данные можно получить, используя http-запрос, или запуская команду терминала, или считывая файл.

    Например, в ОС Linux многие значения можно получить просто читая файл.

    Подробнее о сниппетах можно почитать в документации

    В этой теме можно задавать вопросы по сниппетам и делиться с коллегами готовыми кодами сниппетов.



  • У устройств, которые для получения значений используют сниппеты, есть графа зависимости сниппетов. В документации об этом не написано. Для чего она? Собственно меня интересует при задании интервала запуска сниппета возможность привязки к определенному периоду, как в планировщике cron. Например, запускать каждую минуту в 0 секунд, или каждый час в 15 мин 10 секунд, или каждое воскресенье в 4.30 утра.



  • @intrahouse, @intrapro сделал сниппет для опроса канала I2C MegaD. Работает, однако поскольку никакой обработки не нужно, то может его можно сократить? Собственно вопрос к знатокам js)).

    /**
    * New snippet
    */
    
    module.exports = callback => {
    
      require('http').get('http://192.168.11.22/sec/?pt=33&scl=30&i2c_dev=htu21d', res => {
        if (res.statusCode != 200) {
          res.resume();
          callback("statusCode="+res.statusCode); // Сайт вернул статус ошибки, данные не получены
          return;
        }
    
        let rawData = '';
        res.on('data', chunk => {
          rawData += chunk;
        });
        res.on('end', () => {
          const arr = rawData;
          if (arr && arr.length>1) {
            callback(null, arr);  // Данные получены, парсинг удачен 
          } else {
            callback("Regexp вернул null");  // Данные получены, но парсинг неудачен 
          }
        });
      });
    };
    


  • @Alex_Jet Если работает, то по старому анекдоту про программиста и солнце, лучше и не трогать 🙂

    А серьезно (так понимаю, ожидается вещественное число), обработку результата можно сделать так:

    res.on('end', () => {
          const value = parseFloat(rawData);   
          callback(isNaN(value) ? "Не числовое значение "+rawData : "", value); 
    });
    

    Если придет не число, то в журнале устройства будет сообщение об ошибке



  • Пользователь @int144 написал в Сниппеты:

    У устройств, которые для получения значений используют сниппеты, есть графа зависимости сниппетов. В документации об этом не написано. Для чего она?

    Зависимость - это npm пакет, который может использоваться внутри сниппета (require). Если пакет не установлен, система попытается его установить. Эта возможность пока в экспериментальной стадии.

    Собственно меня интересует при задании интервала запуска сниппета возможность привязки к определенному периоду, как в планировщике cron. Например, запускать каждую минуту в 0 секунд, или каждый час в 15 мин 10 секунд, или каждое воскресенье в 4.30 утра.

    В сниппетах запуск пока только циклический, привязки к временной сетке нет.

    Каждое воскресенье в 4.30 утра легко сделать в расписании, но там сниппеты не используются, значение нужно получать с помощью сценария и присваивать его устройству: this.assign( sensor, value)

    Остальные варианты - только если очень заморочиться 🙂

    Постараемся учесть ваши пожелания в новой версии системы



  • @intrapro, Вас понял, спасибо



  • @intrapro, спасибо! Я об этом говорил. Сам уже квалификацию программиста потерял((. Причем скорее благодаря вашему продукту))) теперь будет возможность поупражняться! Однако делаю вывод, что если есть плагин, то такие простые вещи нужно делать через него. Другое дело если он что-то не поддерживает.



  • Добрый день. Вопрос к разработке: При работе сниппетов съедается оперативная память и в последствии работа всех сниппетов останавливается с ошибками. 1 Гигабайт памяти уходит за 4.5 дня.
    Ошибка лога датчика:

    01.11 15:46:42.285 Next start 01.11 15:46:43
    01.11 15:46:43.292 Started
    01.11 15:46:43.295 ERR:Snippet error { Error: spawn ENOMEM
        at _errnoException (util.js:1021:11)
        at ChildProcess.spawn (internal/child_process.js:325:11)
        at exports.spawn (child_process.js:494:9)
        at Object.exports.execFile (child_process.js:209:15)
        at Object.exports.exec (child_process.js:139:18)
        at module.exports.callback (/var/lib/intrahouse-c/projects/project_1533814451/snippets/SYS.js:6:28)
        at runSnippet (/opt/intrahouse-c/backend/lib/snippetserver/snippetserver.js:87:37)
        at Timerman.onTimerReady (/opt/intrahouse-c/backend/lib/snippetserver/snippetserver.js:178:9)
        at emitOne (events.js:115:13)
        at Timerman.emit (events.js:210:7) code: 'ENOMEM', errno: 'ENOMEM', syscall: 'spawn' }
    
    

    перезагрузка IH без перезагрузки операционки возвращает свободный объем оперативной памяти и работа сниппетов восстанавливается.
    В логе сниппет:

    /**
    * New snippet
    */
    
    module.exports = callback => {
      require('child_process').exec('vcgencmd measure_temp', (error, stdout) => {
        let value;
        if (!error && stdout && stdout.substr(0, 4) == 'temp') {
          value =Math.round(parseFloat(stdout.split('=').pop())); 
        }
        callback( error || value === undefined, value);
      });
    };
    

    В чем причина и как исправить?



  • @Viktor, добрый день.
    Действительно, проблема памяти при многократных частых запусках child process существует.

    github.com/nodejs: Issue 25382. Child process tries to reserve as much mem as parent
    То есть это даже не проблема движка node, а уровень системной ф-и библиотеки libuv.

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

    То же самое происходит, если плагин не может запуститься в нормальном режиме, бесконечно перезапускается, и в конце концов нарывается на ту же ошибку. Поэтому мы советуем неработающие плагины переводить в состояние stop.

    В случае с часто запускаемыми сниппетами лучше обойтись без child_process

    Температуру CPU можно читать напрямую из файла:

    /**
    * CPU Temp
    */
    module.exports = callback => {
      const data = require("fs").readFile('/sys/class/thermal/thermal_zone0/temp', (err, data) => {
      if (err) return callback(err);
    
      callback(null, parseInt(data)/1000);
      });
    }
    

Авторизуйтесь, чтобы ответить