krambox/buderus2mqtt

View on GitHub
scan.js

Summary

Maintainability
C
1 day
Test Coverage
#!/usr/bin/env node
var request = require('request');
var MCrypt = require('mcrypt').MCrypt;
var buffertrim = require('buffertrim');

var config = require('yargs')
  .env('KM200')
  .usage('Scans a KM200 API\n\nUsage: $0 [options]')
  .describe('p', 'KM200 passcode')
  .describe('k', 'KM200 host')
  .describe('h', 'show help')
  .alias({
    'h': 'help',
    'k': 'km200',
    'p': 'passcode'
  })
  .default({
  })
  .version()
  .help('help')
  .argv;

var Table = require('cli-table');
var table = new Table({
  head: ['id', 'type', 'value', 'unit', 'Rec', 'Write', 'min', 'max', 'values'],
  colWidths: [60, 16, 25, 10, 6, 6, 6, 12, 80]
});

var key = Buffer.from(config.passcode, 'hex');
var host = config.km200;
var APIs = [
  '/gateway',
  '/system',
  '/heatSources',
  '/recordings',
  '/notifications',
  '/heatingCircuits',
  '/solarCircuits',
  '/dhwCircuits'
];

var desEcb = new MCrypt('rijndael-128', 'ecb');
desEcb.open(key);

function getKM200 (host, api, done) {
  var options = {
    url: 'http://' + host + api,
    headers: {
      'Content-type': 'application/json',
      'User-Agent': 'TeleHeater/2.2.3'
    }
  };
  request.get(options, function (error, response, body) {
    if (!error && response.statusCode === 200) {
      try {
        var bodyBuffer = Buffer.from(body, 'base64');
        var dataBuffer = buffertrim.trimEnd(desEcb.decrypt(bodyBuffer, 'base64'));
        var result = JSON.parse(dataBuffer.toString());
        done(dataBuffer.toString(), result);
      } catch (e) {
        done({ error: e });
      }
    } else {
      done({ error: error });
    }
  });
}

function requestKM200 (host, APIs) {
  var API = APIs.shift();
  getKM200(host, API, function (result, json) {
    console.error(API, APIs.length);
    if (json !== undefined) analyzeResult(json, APIs);
    if (APIs.length) requestKM200(host, APIs);
    else console.log(table.toString());
  });
}

function analyzeResult (json, APIs) {
  if (json.type === 'refEnum') {
    json.references.forEach(function (e) {
      APIs.unshift(e.id);
    });
  } else buildTableEntry(json);
}

function buildTableEntry (json) {
  var entry = [
    optionalTableString(json.id),
    optionalTableString(json.type),
    optionalTableString(json.value),
    optionalTableString(json.unitOfMeasure),
    optionalTableString(json.recordable),
    optionalTableString(json.writeable),
    optionalTableString(json.minValue),
    optionalTableString(json.maxValue),
    optionalTableString(json.allowedValues)
  ];
  table.push(entry);
}

function optionalTableString (element) {
  if (element === undefined) return '';
  else if (Array.isArray(element)) return JSON.stringify(element);
  else return JSON.stringify(element);
}

requestKM200(host, APIs);