remoteOutput.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. const net = require('net');
  2. var clients = {};
  3. function Client(sock) {
  4. var _this = this;
  5. this.id = sock.remoteAddress;
  6. this.name = this.id;
  7. this.sock = sock;
  8. this.active = true;
  9. this.volumeControl = true;
  10. this.status = {
  11. battery: undefined,
  12. plugged: undefined,
  13. volume: undefined,
  14. lastUpdate: 0
  15. };
  16. this.ping = {
  17. duration: 0,
  18. lastUpdate: 0,
  19. pending: 0
  20. };
  21. this.sock.on('data', (data) => {
  22. var dataStr = data.toString("utf-8");
  23. dataStr.split(/[\r\n]/).forEach(i => i.length ? _this.onData(i) : i);
  24. });
  25. this.sock.on('close', () => {
  26. if (this.active) {
  27. delete clients[this.id];
  28. require("./outputs.js").unregisterOutput(this.id);
  29. this.sock = null;
  30. }
  31. });
  32. this.radios = {};
  33. var allRadios = require("./config.js").RADIOS;
  34. for (var i in allRadios)
  35. this.radios[i] = {
  36. address: allRadios[i],
  37. state: false
  38. };
  39. this.sendInputStates();
  40. }
  41. Client.prototype.onData = function(data) {
  42. if (data.startsWith("HELO"))
  43. this.name = data.substr("HELO".length).trim() +" (" +this.sock.remoteAddress +")";
  44. else if (data.startsWith("STATUS")) {
  45. data = JSON.parse(data.substr("STATUS".length));
  46. if (data) {
  47. this.status.battery = data.battery !== undefined ? data.battery :this.status.battery;
  48. this.status.plugged = data.plugged !== undefined ? data.plugged :this.status.plugged;
  49. this.status.volume = data.volume !== undefined ? data.volume :this.status.volume;
  50. this.status.lastUpdate = Date.now();
  51. }
  52. } else if (data.startsWith("PONG")) {
  53. if (this.ping.pending) {
  54. const now = Date.now();
  55. this.ping = {
  56. lastUpdate: now,
  57. duration: now -this.ping.pending,
  58. pending: 0
  59. };
  60. this.scheduleNextPing();
  61. }
  62. }
  63. }
  64. Client.prototype.requestPing = function() {
  65. if (this.sock) {
  66. this.ping.pending = Date.now();
  67. this.sock.write("PING\n");
  68. }
  69. }
  70. Client.prototype.scheduleNextPing = function() {
  71. setTimeout(() => {this.requestPing();}, 90000); // 1 min 30 sec
  72. }
  73. Client.prototype.getName = function() {
  74. return this.name;
  75. }
  76. Client.prototype.kill = function() {
  77. this.sock.destroy();
  78. this.active = false;
  79. }
  80. Client.prototype.getInputs = function() {
  81. var result = {};
  82. for (var i in this.radios)
  83. result[i] = this.radios[i].state;
  84. return result;
  85. }
  86. Client.prototype.sendInputStates = function() {
  87. this.sock.write("SET" +JSON.stringify(this.radios) +"\n");
  88. }
  89. Client.prototype.setState = function(inputId, state) {
  90. if (!this.radios[inputId])
  91. return false;
  92. if (this.radios[inputId].state !== !!state) {
  93. this.radios[inputId].state = !!state;
  94. this.sendInputStates();
  95. }
  96. return true;
  97. }
  98. Client.prototype.getStatus = function() {
  99. return {
  100. status: this.status.lastUpdate ? this.status : undefined,
  101. ping: this.ping.lastUpdate ? { lastUpdate: this.ping.lastUpdate, duration: this.ping.duration, pending: !!this.ping.pending } : undefined
  102. };
  103. }
  104. Client.prototype.setVolume = function(volume) {
  105. this.sock.write("SETVOL" +volume +"\n");
  106. }
  107. function onClientConnection(sock) {
  108. var cli = new Client(sock);
  109. if (clients[cli.id])
  110. clients[cli.id].kill();
  111. clients[cli.id] = cli;
  112. cli.requestPing();
  113. require("./outputs.js").registerOutput(cli.id, cli);
  114. }
  115. module.exports.init = function() {
  116. net.createServer(onClientConnection).listen(require('./config.js').TCP_PORT, require('./config.js').TCP_LISTEN);
  117. }