<commit_before>var http = require('http');
var net = require('net');
var os = require('os');
var fs = require('fs');
var util = require('util');

function getLocalIPAddress() {
  var interfaces = os.networkInterfaces();

  var ipAddress = "127.0.0.1";
  for (var interfaceName in interfaces) {
    for (var interfaceKey in interfaces[interfaceName]) {
      var interface = interfaces[interfaceName][interfaceKey];
      if ("IPv4" != interface.family || interface.internal != false)
        continue;
      ipAddress = interface.address;
      break;
    }
  }
  return ipAddress;
}

String.prototype.endsWith = function(str) {
  return this.indexOf(str, this.length - str.length) != -1;
}

function genMsg(command) {
  //var header = jspack.jspack.Pack('! 4s I I b 4b', 'ISCP', 16, command.length, 0x1, 0x0, 0x0, 0x0);
  //console.log("HEADER: " + header);
  var header = "ISCP\x00\x00\x00\x10\x00\x00\x00\x08\x01\x00\x00\x00";
  return header + command + '\r';
}

function writeHTMLHead(response) {
  response.writeHead(200, {"Content-Type": "text/html"});
}

function writeJSONHead(response) {
  response.writeHead(200, {"Content-Type": "application/json"});
}



function LutronOutput(id, integrationId, level) {
  this.type = "output";
  this.id = id;
  this.integrationId = integrationId;
  this.level = level;
}

function LutronDevice(id, integrationId, ledCount) {
  this.type = "device";
  this.id = id;
  this.integrationId = integrationId;
  this.leds = new Array(ledCount);
}

function LutronConnection(devices) {
  this.devices = devices !== undefined ? devices : {};
  // Build a reverse mapping so we can update our model from Lutron response
  // messages which are only in terms of integration ids.
  this.integrationIdToDevice = {};
  for (var deviceName in this.devices) {
    var key = "IntegrationID:" + this.devices[deviceName].integrationId;
    console.log("DEV:  "  + key);
    this.integrationIdToDevice[key] = deviceName;
  }

  this.connect();
}

LutronConnection.prototype.logDevice = function(device) {
  var str = util.format("Device=%s IntegrationId=%d Level=%d",
                        device.id, device.integrationId, device.level);
  console.log(str);
}

LutronConnection.prototype.connect = function() {
  this.client = net.connect(23, "10.1.10.32", function() {
    console.log("Connected to Lutron");
  });
  this.client.on("data", this.handleData.bind(this));
  this.client.on("end", this.handleError.bind(this));
  this.client.on("error", this.handleError.bind(this));
}

LutronConnection.prototype.reconnect = function() {
  setTimeout(this.connect.bind(this), 1000);
}

LutronConnection.prototype.parseData = function(data) {
  var data = data.split("\r\n").shift();
  console.log("Lutron: data = ||" + data + "||");
  var params = data.split(",");
  var prefix = params[0];
  var integrationId = params[1];
  switch (prefix) {
  case "~OUTPUT":
    var key = "IntegrationID:" + integrationId;
    if (key in this.integrationIdToDevice) {
      var deviceName = this.integrationIdToDevice[key];
      this.devices[deviceName].level = params[3];
      this.logDevice(this.devices[deviceName]);
    }
    break;
  case "~DEVICE":
    break;
  default:
    break;
  }
}

LutronConnection.prototype.command = function(id, level) {
  this.client.write("#DEVICE,60,1,3\r\n");
}

LutronConnection.prototype.handleConnected = function() {
  for (var deviceName in this.devices) {
    var device = this.devices[deviceName];
    switch (device.type) {
    case "output":
      this.client.write("?OUTPUT," + [device.integrationId, 1].join(","));
      break;
    case "device":
      for (var i = 0; i < device.leds.length; ++i)
        this.client.write("?DEVICE," + [device.integrationId, 81+i, 9].join(","));
      break;
    }
  }
}

LutronConnection.prototype.handleData = function(data) {
  // Coerce stringiness
  data += "";
  switch (data.trim()) {
  case "login:":
    console.log("Writing username...");
    this.client.write("lutron\r\n", "UTF8");
    break;
  case "password:":
    console.log("Writing password...");
    this.client.write("integration\r\n", "UTF8");
    this.handleConnected();
    break;
  default:
    this.parseData(data);
    break;
  }
}

LutronConnection.prototype.handleError = function() {
  console.log("Lutron: Connection Error");
  this.reconnect();
}

var gDevices = {};
gDevices["FrontPorch_Pendants"] = new LutronOutput("FrontPorch_Pendants", 14, 0);

var lutronConnection = new LutronConnection(gDevices);

http.createServer(function(request, response) {
  if (request.url.endsWith("/lutron/command")) {
    if (request.method == "POST" &&
        request.headers["content-type"] == "application/json") {
      var body = "";
      request.on("data", function(chunk) {
        body += chunk.toString();
      });<commit_msg>Moar lutron<commit_after>var http = require('http');
var net = require('net');
var os = require('os');
var fs = require('fs');
var util = require('util');

function getLocalIPAddress() {
  var interfaces = os.networkInterfaces();

  var ipAddress = "127.0.0.1";
  for (var interfaceName in interfaces) {
    for (var interfaceKey in interfaces[interfaceName]) {
      var interface = interfaces[interfaceName][interfaceKey];
      if ("IPv4" != interface.family || interface.internal != false)
        continue;
      ipAddress = interface.address;
      break;
    }
  }
  return ipAddress;
}

String.prototype.endsWith = function(str) {
  return this.indexOf(str, this.length - str.length) != -1;
}

function genMsg(command) {
  //var header = jspack.jspack.Pack('! 4s I I b 4b', 'ISCP', 16, command.length, 0x1, 0x0, 0x0, 0x0);
  //console.log("HEADER: " + header);
  var header = "ISCP\x00\x00\x00\x10\x00\x00\x00\x08\x01\x00\x00\x00";
  return header + command + '\r';
}

function writeHTMLHead(response) {
  response.writeHead(200, {"Content-Type": "text/html"});
}

function writeJSONHead(response) {
  response.writeHead(200, {"Content-Type": "application/json"});
}



function LutronOutput(integrationId, level) {
  this.type = "output";
  this.integrationId = integrationId;
  this.level = level;
}

function LutronDevice(integrationId, ledCount) {
  this.type = "device";
  this.integrationId = integrationId;
  this.leds = new Array(ledCount);
}

function integrationIdKey(integrationId) {
  return "IntegrationId:" + integrationId;
}

function LutronConnection(devices) {
  this.devices = devices !== undefined ? devices : {};
  // Build a reverse mapping so we can update our model from Lutron response
  // messages which are only in terms of integration ids.
  this.integrationIdToDevice = {};
  for (var deviceName in this.devices) {
    var key = integrationIdKey(this.devices[deviceName].integrationId);
    this.integrationIdToDevice[key] = deviceName;
  }

  this.connect();
}

LutronConnection.prototype.logDevice = function(device) {
  var key = integrationIdKey(device.integrationId);
  var str = "";
  switch (device.type) {
    case "output":
      str = util.format("Device=%s IntegrationId=%d Level=%d",
                        this.integrationIdToDevice[key], device.integrationId,
                        device.level);
      break;
    case "device":
      var leds = device.leds.join(",");
      str = util.format("Device=%s IntegrationId=%d Leds=%s",
                        this.integrationIdToDevice[key], device.integrationId,
                        leds);
      break;
    default:
      break;
  }
  console.log(str);
}

LutronConnection.prototype.connect = function() {
  this.client = net.connect(23, "10.1.10.32", function() {
    console.log("Connected to Lutron");
  });
  this.client.on("data", this.handleData.bind(this));
  this.client.on("end", this.handleError.bind(this));
  this.client.on("error", this.handleError.bind(this));
}

LutronConnection.prototype.reconnect = function() {
  setTimeout(this.connect.bind(this), 1000);
}

LutronConnection.prototype.getDeviceForIntegrationId = function(integrationId) {
  var key = integrationIdKey(integrationId);
  if (key in this.integrationIdToDevice) {
    var deviceName = this.integrationIdToDevice[key];
    return this.devices[deviceName];
  }
  return null;
}

LutronConnection.prototype.parseData = function(data) {
  var data = data.split("\r\n").shift();
  if (data.substring(0, 5) == "QNET>")
    data = data.substring(5);
  data = data.trim();
  if (data == "")
    return;
  console.log("Lutron: data = |" + data + "|");
  var params = data.split(",");
  var device = this.getDeviceForIntegrationId(params[1]);
  if (device)
    this.logDevice(device);
  
  switch (params[0]) {
  case "~OUTPUT":
    if (device && (params[2] == 1))
      device.level = params[3];
    break;
  case "~DEVICE":
    if (device) {
      var ledIndex = params[3] - 81;
      if (ledIndex >= 0 && ledIndex < device.leds.length)
        device.leds[ledIndex] = params[4];
    }
    break;
  default:
    break;
  }
}

LutronConnection.prototype.command = function(id, level) {
  this.client.write("#DEVICE,60,1,3\r\n");
}

LutronConnection.prototype.handleConnected = function() {
  for (var deviceName in this.devices) {
    var device = this.devices[deviceName];
    switch (device.type) {
    case "output":
      var command = "?OUTPUT," + [device.integrationId, 1].join(",") + "\r\n";
      this.client.write(command);
      break;
    case "device":
      for (var i = 0; i < device.leds.length; ++i) {
        var command = "?DEVICE," + [device.integrationId, 81+i, 9].join(",") +
            "\r\n";
        this.client.write(command);
      }
      break;
    }
  }
}

LutronConnection.prototype.handleData = function(data) {
  // Coerce stringiness
  data += "";
  switch (data.trim()) {
  case "login:":
    this.client.write("lutron\r\n", "UTF8");
    break;
  case "password:":
    this.client.write("integration\r\n", "UTF8");
    this.handleConnected();
    break;
  default:
    this.parseData(data);
    break;
  }
}

LutronConnection.prototype.handleError = function() {
  console.log("Lutron: Connection Error");
  this.reconnect();
}

var gDevices = {};
gDevices["FrontPorch_Pendants"] = new LutronOutput(14, 0);
gDevices["FrontPorch_Sconces"] = new LutronOutput(15, 0);
gDevices["Kitchen_MudRoom_Switch"] = new LutronDevice(60, 6);
gDevices["MudRoom_Garage_Switch"] = new LutronDevice(49, 6);

var lutronConnection = new LutronConnection(gDevices);

http.createServer(function(request, response) {
  if (request.url.endsWith("/lutron/command")) {
    if (request.method == "POST" &&
        request.headers["content-type"] == "application/json") {
      var body = "";
      request.on("data", function(chunk) {
        body += chunk.toString();
      });
{'fraction_non_alphanumeric': 0.1597300337457818, 'fraction_numerical': 0.01677915260592426, 'mean_word_length': 3.584873227331328, 'pattern_counts': {'":': 18, '<': 6, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2828524', 'n_tokens_mistral': 3661, 'n_tokens_neox': 3498, 'n_words': 712}