homebridge-optoma-projector
Version:
Homebridge plugin for optoma projectors
192 lines (155 loc) • 7.2 kB
JavaScript
// Accessory for controlling Marantz AVR via HomeKit
var inherits = require('util').inherits;
var SerialPort = require("serialport");
var Service, Characteristic;
// Use a `\r\n` as a line terminator
const parser = new SerialPort.parsers.Readline({
delimiter: '\r'
});
module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
// homebridge.registerAccessory("homebridge-marantz-rs232", "Marantz-RS232", optomaProjector);
homebridge.registerAccessory("homebridge-optoma-projector", "optoma-Projector", optomaProjector);
function optomaProjector(log, config) {
// configuration
this.name = config['name'];
this.path = config['path'];
this.timeout = config.timeout || 1000;
this.queue = [];
this.callbackQueue = [];
this.ready = true;
this.log = log;
this.serialPort = new SerialPort(this.path, {
baudRate: 9600,
dataBits: 8,
stopBits: 1,
parity: 'none',
autoOpen: false
}); // this is the openImmediately flag [default is true]
this.serialPort.pipe(parser);
parser.on('data', function(data) {
this.log("Received data: " + data);
this.serialPort.close(function(error) {
this.log("Closing connection");
if(error) this.log("Error when closing connection: " + error)
var callback;
if(this.callbackQueue.length) callback = this.callbackQueue.shift()
if(callback) callback(data,0);
}.bind(this)); // close after response
}.bind(this));
}
// Custom Characteristics and service..
optomaProjector.prototype = {
send: function(cmd, callback) {
this.sendCommand(cmd, callback);
//if (callback) callback();
},
exec: function() {
// Check if the queue has a reasonable size
if(this.queue.length > 100) {
this.queue.clear();
this.callbackQueue.clear();
}
this.queue.push(arguments);
this.process();
},
sendCommand: function(command, callback) {
this.log("sendCommand function: serialPort.open");
if(this.serialPort.isOpen){
this.log("serialPort is already open...");
if(callback) callback(0,1);
}
else{
this.serialPort.open(function (error) {
if(error) {
this.log("Error when opening serialport: " + error);
if(callback) callback(0,error);
}
else {
if(callback) this.callbackQueue.push(callback);
this.serialPort.write(command, function(err) {
if(err) this.log("Write error = " + err);
//this.serialPort.drain();
}.bind(this));
}
// if(callback) callback(0,0);
}.bind(this));
}
},
process: function() {
if (this.queue.length === 0) return;
if (!this.ready) return;
var self = this;
this.ready = false;
this.send.apply(this, this.queue.shift());
setTimeout(function () {
self.ready = true;
self.process();
}, this.timeout);
},
getPowerState: function(callback) {
// var cmd = String.fromCharCode(0x7e) + "00124 1" + String.fromCharCode(0x0d) + "\r";
// var cmd = "~00150 16\r";
//POWER OFF: let cmd = new Uint8Array([0x7E, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x0D])
// let cmd = new Uint8Array([0x7E, 0x30, 0x30, 0x31, 0x32, 0x34, 0x20, 0x31, 0x0D])
//let cmd = new Uint32Array([0x7E, 0x30, 0x30, 0x31, 0x32, 0x34, 0x20, 0x31, 0x0D])
//let cmd = new Buffer.from([0x7E, 0x30, 0x30, 0x31, 0x32, 0x34, 0x20, 0x31, 0x0D])
//cmd.toString('hex');
const cmd = Buffer.from('~087 1\r', 'ascii');
//var cmd = (buf.toString('hex'));
this.log("getPowerState called and sending cmd: " + cmd);
// this.log("getPowerState");
this.exec(cmd, function(response,error) {
this.log("Power state is: " + response);
if (response && response.indexOf("Ok") > -1) {
if(callback) callback(null, true);
}
else {
if(callback) callback(null, false);
}
}.bind(this))
},
setPowerState: function(powerOn, callback) {
var cmd;
if (powerOn) {
cmd = String.fromCharCode(0x7e) + "0000 1" + String.fromCharCode(0x0d) + "\r";
this.log("Set", this.name, "to on");
}
else {
cmd = String.fromCharCode(0x7e) + "0000 0" + String.fromCharCode(0x0d) + "\r";
this.log("Set", this.name, "to off");
}
this.exec(cmd, function(response,error) {
if (error) {
this.log('Serial power function failed: %s');
if(callback) callback(error);
}
else {
this.log('Serial power function succeeded!');
if(callback) callback();
}
}.bind(this));
},
identify: function(callback) {
this.log("Identify requested!");
this.setPowerState(true); // turn on
if(callback) callback();
},
getServices: function() {
var that = this;
var informationService = new Service.AccessoryInformation();
informationService
.setCharacteristic(Characteristic.Name, this.name)
.setCharacteristic(Characteristic.Manufacturer, "Optoma")
.setCharacteristic(Characteristic.Model, "UHD50")
.setCharacteristic(Characteristic.SerialNumber, "1234567890");
var switchService = new Service.Switch("Power State", "power_on");
switchService
.getCharacteristic(Characteristic.On)
.on('get', this.getPowerState.bind(this))
.on('set', this.setPowerState.bind(this));
return [informationService, switchService];
}
}
};