Thickness1

index.js

Sep 30th, 2017
74
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. var EventEmitter = require('events').EventEmitter;
  2. var net = require('net');
  3. var util = require('util');
  4.  
  5. var topic, message;
  6. var previous = {
  7. 0: "",
  8. 1: "",
  9. 2: "",
  10. 3: "",
  11. 4: "",
  12. 5: "",
  13. 6: "",
  14. 7: "",
  15. 8: "",
  16. 9: "",
  17. 10: "",
  18. 11: "",
  19. 12: "",
  20. 13: "",
  21. 14: "",
  22. 15: "",
  23. 16: "",
  24. 17: "",
  25. 18: "",
  26. 19: "",
  27. 20: "",
  28. 21: "",
  29. 22: "",
  30. 23: "",
  31. 24: "",
  32. 25: "",
  33. 26: "",
  34. 27: "",
  35. 28: "",
  36. 29: "",
  37. 30: "",
  38. 31: "",
  39. 32: "",
  40. 33: "",
  41. 48: "",
  42. 49: "",
  43. 50: "",
  44. 56: "",
  45. 57: "",
  46. 58: "",
  47. 100: "",
  48. 115: "",
  49. 116: "",
  50. 117: "",
  51. 118: "",
  52. 119: "",
  53. 120: "",
  54. 121: "",
  55. 122: "",
  56. 123: "",
  57. 124: "",
  58. 125: "",
  59. 126: "",
  60. 127: ""
  61. };
  62.  
  63. var opentherm_ids = {
  64. 0: "flame_status",
  65. 1: "control_setpoint",
  66. 2: "master_config_flags/master_member_id",
  67. 3: "slave_config_flags/slave_member_id",
  68. 4: "remote_command",
  69. 5: "application-specific_fault_flag/OEM_fault_code",
  70. 6: "remote_boiler_parameter_transfer-enable/read_write_flags",
  71. 7: "cooling_control_signal",
  72. 8: "control_setpoint_2nd_circuit",
  73. 9: "remote_override_setpoint",
  74. 10: "number_transparent_slave_parameters_supported_slave",
  75. 11: "index_number/value_referred_to_transparent_slave_parameter",
  76. 12: "size_of_fault_history_buffer_slave",
  77. 13: "index_number/value_referred_to_fault_history_buffer",
  78. 14: "max_relative_modulation",
  79. 15: "max_boiler_capacity/minimum_boiler_modulation",
  80. 16: "room_setpoint",
  81. 17: "relative_modulation",
  82. 18: "ch_water_pressure",
  83. 19: "flow_dhw",
  84. 20: "day_of_week/time_of_day",
  85. 21: "calender_date",
  86. 22: "calender_year",
  87. 23: "room_setpoint_2nd_circuit",
  88. 24: "room_temperature",
  89. 25: "boiler_water_temperature",
  90. 26: "dhw_temperature",
  91. 27: "outside_temperature",
  92. 28: "return_water_temperature",
  93. 29: "solar_storage_temperature",
  94. 30: "solar_collector_temperature",
  95. 31: "flow_water_temperature_2nd_circuit",
  96. 32: "dhw_temperature_2",
  97. 33: "boiler_exhaust_temperature",
  98. 48: "dhw_upper_bound/dhw_lower_bound",
  99. 49: "max_ch_setpoint_upper_bound/lower_bound",
  100. 50: "otc_curve_upper_bound/lower_bound",
  101. 56: "dhw_setpoint",
  102. 57: "max_ch_setpoint",
  103. 58: "otc_curve_ratio",
  104. 100: "remote_override_function",
  105. 115: "OEM_diagnostic_code",
  106. 116: "burner_starts",
  107. 117: "ch_pump_starts",
  108. 118: "dhw_pump_starts",
  109. 119: "dhw_burner_starts",
  110. 120: "burner_operation_hours",
  111. 121: "ch_pump_operation_hours",
  112. 122: "dhw_pump_operation_hours",
  113. 123: "dhw_burner_operation_hours",
  114. 124: "opentherm_version_master",
  115. 125: "opentherm_version_slave",
  116. 126: "master_version",
  117. 127: "slave_version"
  118. };
  119.  
  120. var opentherm_ids_types = {
  121. 0: "flag8",
  122. 1: "f8.8",
  123. 2: "flag8",
  124. 3: "flag8",
  125. 4: "u8",
  126. 5: "flag8",
  127. 6: "flag8",
  128. 7: "f8.8",
  129. 8: "f8.8",
  130. 9: "f8.8",
  131. 10: "u8",
  132. 11: "u8",
  133. 12: "u8",
  134. 13: "u8",
  135. 14: "f8.8",
  136. 15: "u8",
  137. 16: "f8.8",
  138. 17: "f8.8",
  139. 18: "f8.8",
  140. 19: "f8.8",
  141. 20: "u8",
  142. 21: "u8",
  143. 22: "u16",
  144. 23: "f8.8",
  145. 24: "f8.8",
  146. 25: "f8.8",
  147. 26: "f8.8",
  148. 27: "f8.8",
  149. 28: "f8.8",
  150. 29: "f8.8",
  151. 30: "f8.8",
  152. 31: "f8.8",
  153. 32: "f8.8",
  154. 33: "s16",
  155. 48: "s8",
  156. 49: "s8",
  157. 50: "s8",
  158. 56: "f8.8",
  159. 57: "f8.8",
  160. 58: "f8.8",
  161. 100: "flag8",
  162. 115: "u16",
  163. 116: "u16",
  164. 117: "u16",
  165. 118: "u16",
  166. 119: "u16",
  167. 120: "u16",
  168. 121: "u16",
  169. 122: "u16",
  170. 123: "u16",
  171. 124: "f8.8",
  172. 125: "f8.8",
  173. 126: "u8",
  174. 127: "u8"
  175.  
  176. };
  177.  
  178. util.inherits(OTGateway, EventEmitter);
  179.  
  180. function padLeft(nr, n, str){
  181. return Array(n-String(nr).length+1).join(str||'0')+nr;
  182. }
  183.  
  184. function OTGateway(ip, port) {
  185.  
  186. this.ip = ip;
  187. this.port = port;
  188. this.interval = 60000;
  189. this.isConnected = false;
  190. this.busy = false;
  191. this.callback = null;
  192. this.dutyCycle = 0;
  193. this.memorySlots = 0;
  194.  
  195. this.rooms = [];
  196. this.devices = {};
  197. this.deviceCount = 0;
  198. this.client = new net.Socket();
  199. var self = this;
  200. this.client.on('error', function(err){
  201. self.emit('error', err);
  202. });
  203.  
  204. this.client.on('data', this.onData.bind(this));
  205.  
  206. this.connect();
  207. }
  208.  
  209. OTGateway.prototype.connect = function () {
  210. if (!this.isConnected) {
  211. this.client.connect(this.port, this.ip, function() {
  212. //console.log('Connected');
  213. this.isConnected = true;
  214. this.emit('connected');
  215. }.bind(this));
  216. } else {
  217. // this.send('l:\r\n');
  218. }
  219. setTimeout(this.connect.bind(this), this.interval);
  220. };
  221.  
  222. OTGateway.prototype.send = function (message, callback) {
  223. if (!this.busy) {
  224. //console.log('Sending command: ' + message.substr(0,1));
  225. this.busy = true;
  226. this.client.write(message + '\r\n', 'utf-8', callback);
  227. }
  228. };
  229.  
  230. OTGateway.prototype.onData = function (data) {
  231. data = data.toString('utf-8');
  232. data = data.split('\r\n');
  233. data.forEach(function (line) {
  234. if (line.length > 0) {
  235. // check for OT packets
  236. // console.log(line);
  237. opentherm_target = line.slice(0, 1); // B, T, A, R, E
  238. // console.log(opentherm_target);
  239. opentherm_type = line.slice(1, 2); //
  240. opentherm_id = parseInt(line.slice(3, 5), 16); //
  241. opentherm_payload = line.slice(-4); // last 4 chars
  242.  
  243. if (opentherm_target == "B" || opentherm_target == "T" || opentherm_target == "A" || opentherm_target == "R" || opentherm_target == "E") {
  244. //if (opentherm_target == "B" || opentherm_target == "T" || opentherm_target == "A") {
  245. if (opentherm_type == "1" || opentherm_type == "4" || opentherm_type == "C" || opentherm_type == "9") {
  246. //if (opentherm_type == "1" || opentherm_type == "4") {
  247. if (opentherm_id in opentherm_ids) {
  248. // topic = opentherm_ids[opentherm_id];
  249. topic = opentherm_target + "_" + opentherm_ids[opentherm_id];
  250. // console.log(topic);
  251. switch (opentherm_ids_types[opentherm_id]) {
  252. case 'flag8':
  253. message = parseInt(opentherm_payload, 16).toString(2);
  254. for (var i = 15 - message.length; i >= 0; i--) {
  255. message = "0" + message;
  256. };
  257. break;
  258.  
  259. case 'f8.8':
  260. message = (parseInt(opentherm_payload, 16) / 256).toFixed(2);
  261. break;
  262.  
  263. case 'u16':
  264. message = parseInt(opentherm_payload, 16);
  265. break;
  266.  
  267. case 'u8':
  268. message = parseInt(opentherm_payload, 8);
  269. break;
  270.  
  271. case 's8':
  272. message = 0;
  273. break;
  274. }
  275.  
  276. //console.log(String(previous[topic] + previous[message]));
  277. //console.log(String(topic+message));
  278. //console.log(String((topic + message) (previous[topic] + previous[message])));
  279. if ((message) != (previous[opentherm_id])) {
  280. this.emit(topic, String(message));
  281. // previous[topic] = topic;
  282. previous[opentherm_id] = message;
  283. }
  284. }
  285. }
  286. } //15:12:42.394368 AC0090000 Read-Data Remote override room setpoint: 0.00
  287.  
  288. if ((opentherm_target == "T" && (opentherm_type == "T" || opentherm_type == "C")) || line == "NG" || line == "SE" || line == "BV" || line == "OR" || line == "NS" || line == "NF" || line == "OE") {
  289. this.emit('response',line);
  290. }
  291.  
  292. }
  293. }.bind(this));
  294.  
  295. this.busy = false;
  296. };
  297.  
  298. //NOT functional atm
  299. OTGateway.prototype.setTemperature = function (mode, temperature, callback) {
  300.  
  301. if (!this.isConnected) {
  302. callback(new Error("Not connected"));
  303. return;
  304. }
  305.  
  306. var data;
  307. switch (mode) {
  308. case 'auto':
  309. data = 'TT=00';
  310. break;
  311. case 'manu':
  312. data = 'TT=' + temperature;
  313. break;
  314. case 'boost':
  315. data = 'TC=' + temperature;
  316. break;
  317. default:
  318. callback(new Error('Unknown mode: ' + mode));
  319. return false;
  320. }
  321.  
  322. this.send(data, function(err) {
  323. if(err && callback) {
  324. callback(err);
  325. callback = null;
  326. }
  327. });
  328.  
  329. this.once('response', function(res) {
  330. if(!callback) {
  331. return;
  332. }
  333. if(res == "NG" || res == "SE" || res == "BV" || res == "OR" || res == "NS" || res == "NF" || res == "OE") {
  334. var reason = "";
  335. switch(res) {
  336. case "NG":
  337. reason = "No Good: The command code is unknown.";
  338. break;
  339. case "SE":
  340. reason = "Syntax Error: The command contained an unexpected character or was incomplete.";
  341. break;
  342. case "BV":
  343. reason = "Bad Value: The command contained a data value that is not allowed.";
  344. break;
  345. case "OR":
  346. reason = "Out of Range: A number was specified outside of the allowed range.";
  347. break;
  348. case "NS":
  349. reason = "No Space: The alternative Data-ID could not be added because the table is full.";
  350. break;
  351. case "NF":
  352. reason = "Not Found: The specified alternative Data-ID could not be removed because it does not exist in the table.";
  353. break;
  354. case "OE":
  355. reason = "Overrun Error: The processor was busy and failed to process all received characters.";
  356. break;
  357. }
  358. callback(new Error('Command was rejected, Reason: ' + reason));
  359. } else {
  360. callback(null);
  361. }
  362. callback = null;
  363. });
  364. };
  365.  
  366. module.exports = OTGateway;
RAW Paste Data