From ac7e26915d9a445785bc2981c956bc92dcd3b5fb Mon Sep 17 00:00:00 2001 From: Tim Cameron Ryan Date: Thu, 22 May 2014 23:51:55 -0700 Subject: [PATCH] Cleans up code and adds licensing information. --- COPYRIGHT | 11 +++ LICENSE-APACHE | 202 +++++++++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 26 ++++++ README.md | 43 +++++---- examples/infrared.js | 3 + index.js | 194 ++++++++++++++++------------------------- 6 files changed, 343 insertions(+), 136 deletions(-) create mode 100644 COPYRIGHT create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..6f4679b --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,11 @@ +The Infrared Module project is copyright 2014 +Technical Machine, Inc. + +Licensed under the Apache License, Version 2.0 + or the MIT +license , +at your option. All files in the project carrying such +notice may not be copied, modified, or distributed except +according to those terms. + diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..bd89c98 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..2a5d676 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2013-2014 Technical Machine, Inc + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff --git a/README.md b/README.md index d44d7e7..6b5ce63 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,29 @@ npm install ir-attx4 ``` ##Example ```js +/********************************************* +This infrared module example transmits the +power signal sequence of an Insignia brand +television every three seconds, while also +listening for (and logging) any incoming +infrared data. +*********************************************/ + +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ + var tessel = require('tessel'); // Connect the IR module to port a -var hardware = tessel.port("A"); +var hardware = tessel.port['A']; // Import library and connect to module -var infrared = require('ir-attx4').use(hardware); +var infrared = require('../').use(hardware); + +var counter = 0; // When we're connected -infrared.on('ready', function(err) { +infrared.on('ready', function() { if (!err) { console.log("Connected to IR!"); @@ -45,32 +58,26 @@ var powerTV = function() { console.log("TV Should be powered..."); } }); -} +}; ``` ##Methods -The primary method for sending data. The first argument is a frequency of signal in Hz, typically 38 but can range from 36 to 40. The second argument is a buffer -of unsinged 16 bit integers representing the number of microseconds the transmission should be on. The max length of the signal durations is 100 durations. -* **`infrared`.sendRawSignal(frequency, signalDurations, callback)** +##### * `infrared.sendRawSignal(frequency, signalDurations, callback)` The primary method for sending data. The first argument is a frequency of signal in Hz, typically 38 but can range from 36 to 40. The second argument is a buffer of unsigned 16 bit integers representing the number of microseconds the transmission should be on. The max length of the signal durations is 100 durations. + +##### * `infrared.setListening(set, callback)` Determines whether the module is listening for incoming signals. Will automatically be set and unset depending on listeners for the `data` event. -Determines whether the module is listening for incoming signals -Will automatically be set and unset depending on listeners for the -`data` event. -* **`infrared`.setListening(set, callback)** ## Events -Called when the module is detected and ready to receive commands -* **`infrared`.on(`ready`, callback)** +##### * `infrared.on('data', callback(data))` Emitted when an infrared signal is detected. + +##### * `infrared.on('error', callback(err))` Emitted when there is an error communicating with the module. -Called when an IR signal is detected -* **`infrared`.on(`data`, callback(data))** +##### * `infrared.on('ready', callback())` Emitted upon first successful communication between the Tessel and the module. -Called when there is an error connecting to the module -* **`infrared`.on(`error`, callback(err))** ## License -MIT/Apache 2.0 +Released under the MIT and Apache 2.0 licenses. diff --git a/examples/infrared.js b/examples/infrared.js index df87ca7..fa85bf5 100644 --- a/examples/infrared.js +++ b/examples/infrared.js @@ -1,3 +1,6 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ + var tessel = require('tessel'); // Connect the IR module to port a diff --git a/index.js b/index.js index 3c471b1..66a508f 100644 --- a/index.js +++ b/index.js @@ -7,7 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -var util = require('util'); +var util = require('util'); var EventEmitter = require('events').EventEmitter; var PACKET_CONF = 0x55; @@ -38,30 +38,29 @@ var Infrared = function(hardware, callback) { var self = this; // If we get a new listener - this.on('newListener', function(event) { + this.on('newListener', function (event) { // And they are listening for rx data and we haven't been yet - if (event == "data" && !this.listeners(event).length) { - self.setListening(1); + if (event == 'data' && !this.listeners(event).length) { + self.setListening(1); } }); - this.on('removeListener', function(event) { + this.on('removeListener', function (event) { // If this was for the rx data event and there aren't any more listeners - if (event == "data" && !this.listeners(event).length) { - self.setListening(0); + if (event == 'data' && !this.listeners(event).length) { + self.setListening(0); } }); // Make sure we can communicate with the module - this._establishCommunication(3, function(err, version) { + this._establishCommunication(3, function (err, version) { if (err) { - setImmediate( function() { + setImmediate(function () { // Emit an error event self.emit('error'); }); - } - else { - setImmediate( function() { + } else { + setImmediate(function () { // Emit a ready event self.emit('ready'); // Start listening for IRQ interrupts @@ -81,14 +80,14 @@ var Infrared = function(hardware, callback) { util.inherits(Infrared, EventEmitter); -Infrared.prototype._IRQHandler = function() { +Infrared.prototype._IRQHandler = function () { var self = this; // If we are not in the middle of transmitting if (!self.transmitting) { // Receive the durations - self._fetchRXDurations( function fetched() { - // Start listening for IRQ interrupts again - self.irq.watch('high', self._IRQHandler.bind(self)); + self._fetchRXDurations(function fetched () { + // Start listening for IRQ interrupts again + self.irq.watch('high', self._IRQHandler.bind(self)); }); } else { // If we are, check back in a little bit @@ -96,37 +95,33 @@ Infrared.prototype._IRQHandler = function() { } }; -Infrared.prototype.setListening = function(set, callback) { +Infrared.prototype.setListening = function (set, callback) { var self = this; var cmd = set ? RX_START_CMD : RX_STOP_CMD; - self.spi.transfer(new Buffer([cmd, 0x00, 0x00]), function listeningSet(err, response) { - self._validateResponse(response, [PACKET_CONF, cmd], function(valid) { + self.spi.transfer(new Buffer([cmd, 0x00, 0x00]), function listeningSet (err, response) { + self._validateResponse(response, [PACKET_CONF, cmd], function (valid) { if (!valid) { - return callback && callback(new Error("Invalid response on setting rx on/off.")); - } - else { + callback && callback(new Error("Invalid response on setting rx on/off.")); + } else { self.listening = set ? true : false; - - if (callback) { - callback(); - } + callback && callback(); } }); }); }; -Infrared.prototype._fetchRXDurations = function(callback) { +Infrared.prototype._fetchRXDurations = function (callback) { var self = this; // We have to pull chip select high in case we were in the middle of something else // this.chipSelect.high(); - self.spi.transfer(new Buffer([IR_RX_AVAIL_CMD, 0x00, 0x00, 0x00]), function spiComplete(err, response) { + self.spi.transfer(new Buffer([IR_RX_AVAIL_CMD, 0x00, 0x00, 0x00]), function spiComplete (err, response) { // DO something smarter than this eventually - self._validateResponse(response, [PACKET_CONF, IR_RX_AVAIL_CMD, 1], function(valid) { + self._validateResponse(response, [PACKET_CONF, IR_RX_AVAIL_CMD, 1], function (valid) { if (valid) { var numInt16 = response[3]; @@ -136,34 +131,23 @@ Infrared.prototype._fetchRXDurations = function(callback) { var rxHeader = [IR_RX_CMD, 0x00, 0x00]; var packet = rxHeader.concat(new Array(numBytes)); - // Push the stop bit on there. packet.push(FIN_CONF); - packet = new Buffer(packet); - - self.spi.transfer(packet, function spiComplete(err, response) { - - var fin = response[response.length-1]; + self.spi.transfer(new Buffer(packet), function spiComplete (err, response) { + var fin = response[response.length - 1]; if (fin != FIN_CONF) { console.warn("Warning: Received Packet Out of Frame."); - if (callback) { - callback(); - } - } - - else { + callback && callback(); + } else { // Remove the header echoes at the beginning and stop bit - var buf = response.slice(rxHeader.length, response.length-1); + var buf = response.slice(rxHeader.length, response.length - 1); // Emit the buffer self.emit('data', buf); - - if (callback) { - callback(); - } + callback && callback(); } }); } @@ -171,49 +155,38 @@ Infrared.prototype._fetchRXDurations = function(callback) { }); }; -Infrared.prototype.sendRawSignal = function(frequency, signalDurations, callback) { +Infrared.prototype.sendRawSignal = function (frequency, signalDurations, callback) { if (frequency <= 0) { - if (callback) { - callback(new Error("Invalid frequency. Must be greater than zero. Works best between 36-40.")); - } - + callback && callback(new Error("Invalid frequency. Must be greater than zero. Works best between 36-40.")); return; - } - else if (signalDurations.length > MAX_SIGNAL_DURATION) { - if (callback) { - callback(new Error("Invalid buffer length. Must be between 1 and ", MAX_SIGNAL_DURATION)); - } + } + if (signalDurations.length > MAX_SIGNAL_DURATION) { + callback && callback(new Error("Invalid buffer length. Must be between 1 and ", MAX_SIGNAL_DURATION)); return; } - else { - this.transmitting = true; - - var self = this; - - // Make the packet - var tx = this._constructTXPacket(frequency, signalDurations); + this.transmitting = true; + var self = this; - // Send it over - this.spi.transfer(tx, function spiComplete(err, response) { + // Make the packet + var tx = this._constructTXPacket(frequency, signalDurations); - self.transmitting = false; - var err; + // Send it over + this.spi.transfer(tx, function spiComplete (err, response) { + self.transmitting = false; - // If there was an error already, set immediate on the callback - if (!self._validateResponse(response, [PACKET_CONF, IR_TX_CMD, frequency, signalDurations.length/2])) { - err = new Error("Invalid response from raw signal packet."); - } - - if (callback) { - callback(err); - } - }); - } + // If there was an error already, set immediate on the callback + var err = null; + if (!self._validateResponse(response, [PACKET_CONF, IR_TX_CMD, frequency, signalDurations.length/2])) { + err = new Error("Invalid response from raw signal packet."); + } + + callback && callback(err); + }); }; -Infrared.prototype._constructTXPacket = function(frequency, signalDurations) { +Infrared.prototype._constructTXPacket = function (frequency, signalDurations) { // Create array var tx = []; // Add command @@ -222,12 +195,12 @@ Infrared.prototype._constructTXPacket = function(frequency, signalDurations) { tx.push(frequency); // Add length of signal durations in terms of int16s - tx.push(signalDurations.length/2); + tx.push(signalDurations.length / 2); // For each signal duration for (var i = 0; i < signalDurations.length; i++) { - // Send upper and lower bits - tx.push(signalDurations.readUInt8(i)); + // Send upper and lower bits + tx.push(signalDurations.readUInt8(i)); } // Put a dummy bit to get the last echo tx.push(0x00); @@ -235,16 +208,13 @@ Infrared.prototype._constructTXPacket = function(frequency, signalDurations) { // Put the finish confirmation tx.push(FIN_CONF); - tx = new Buffer(tx); - - // return - return tx; + return new Buffer(tx); }; -Infrared.prototype._establishCommunication = function(retries, callback){ +Infrared.prototype._establishCommunication = function (retries, callback){ var self = this; // Grab the firmware version - self.getFirmwareVersion(function(err, version) { + self.getFirmwareVersion(function (err, version) { // If it didn't work if (err) { // Subtract number of retries @@ -258,63 +228,51 @@ Infrared.prototype._establishCommunication = function(retries, callback){ else { self._establishCommunication(retries, callback); } - } - // If there was no error - else { + } else { // Connected successfully self.connected = true; // Call callback with version - if (callback) { - callback(null, version); - } + callback && callback(null, version); } }); }; -Infrared.prototype.getFirmwareVersion = function(callback) { +Infrared.prototype.getFirmwareVersion = function (callback) { var self = this; - self.spi.transfer(new Buffer([FIRMWARE_CMD, 0x00, 0x00]), function spiComplete(err, response) { + self.spi.transfer(new Buffer([FIRMWARE_CMD, 0x00, 0x00]), function spiComplete (err, response) { if (err) { return callback(err, null); - } - else if (self._validateResponse(response, [false, FIRMWARE_CMD]) && response.length === 3) - { - if (callback) { - callback(null, response[2]); - } - } - else - { - if (callback) { - callback(new Error("Error retrieving Firmware Version")); - } + } else if (self._validateResponse(response, [false, FIRMWARE_CMD]) && response.length === 3) { + callback && callback(null, response[2]); + } else { + callback && callback(new Error("Error retrieving Firmware Version")); } }); }; -Infrared.prototype._validateResponse = function(values, expected, callback) { - +Infrared.prototype._validateResponse = function (values, expected, callback) { var res = true; - for (var index = 0; index < expected.length; index++) { - - if (expected[index] === false) continue; - + if (expected[index] == false) { + continue; + } if (expected[index] != values[index]) { res = false; break; } } - if (callback) { - callback(res); - } - + callback && callback(res); return res; }; + +/** + * Public API + */ + exports.Infrared = Infrared; exports.use = function (hardware, callback) { return new Infrared(hardware, callback); -}; \ No newline at end of file +};