UNPKG

smoke-signal-js

Version:
379 lines (322 loc) 11.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>index.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <script src="scripts/nav.js" defer></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav > <input type="text" id="nav-search" placeholder="Search" /> <h2><a href="index.html">Home</a></h2><h2><a href="https://github.com/Smoke3785/smokesignal-js" target="_blank" class="menu-item" id="repository" >Github repo</a></h2><h3>Global</h3><ul><li><a href="global.html#getRequestObjectData">getRequestObjectData</a></li><li><a href="global.html#getSendCommandData">getSendCommandData</a></li><li><a href="global.html#getSendObjectData">getSendObjectData</a></li><li><a href="global.html#processBytes">processBytes</a></li><li><a href="global.html#requestObject">requestObject</a></li><li><a href="global.html#sendCommand">sendCommand</a></li><li><a href="global.html#sendObject">sendObject</a></li></ul> </nav> <div id="main"> <h1 class="page-title">index.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>// Dependencies var ByteBuffer = require('bytebuffer'); const helperFunctions = require('smoke-machine-js'); // Variables const OBJECT_HEADER_SIZE = 17; //Type (1) + ObjectNo (4) + InstanceNo (4) + Start (4) + Length (4). const COMMAND_HEADER_SIZE = 9; //Type (1) + CommandType (4) + InstanceNo (4). 🤷‍♂️ const MESSAGE_TYPE_REQUEST = 1; const MESSAGE_TYPE_SEND = 2; const MESSAGE_TYPE_COMMAND = 3; const SIZEOF_INT = 4; /** * Encodes an object into a Tobject ( a bytebuffer prepended with metadata) to send data to a LaunchLike server. * @param {object} { lObject, lInstanceNumber, lStart, cData } * @returns {bytebuffer} */ const getSendObjectData = ({ lObject, lInstanceNumber, lStart, cData }) => { const bb = new ByteBuffer(OBJECT_HEADER_SIZE + cData.length); bb.writeByte(MESSAGE_TYPE_SEND); bb.writeInt(lObject); bb.writeInt(lInstanceNumber); bb.writeInt(lStart); bb.writeInt(cData.length); bb.append(cData); return bb.buffer; }; /** * Encodes data required to send a command to a LaunchLike server. * @param {object} {lCommand, lInstanceNumber} * @returns {bytebuffer} */ const getSendCommandData = ({ lCommand, lInstanceNumber }) => { const bb = new ByteBuffer(COMMAND_HEADER_SIZE); bb.writeByte(MESSAGE_TYPE_COMMAND); bb.writeInt(lCommand); bb.writeInt(lInstanceNumber); return bb.buffer; }; /** * Encodes data required to make an object request to a LaunchLike server. * @param {object} {lObject, lInstanceNumber, lStart, lLength} * @returns {bytebuffer} */ const getRequestObjectData = ({ lObject, lInstanceNumber, lStart, lLength, }) => { const bb = new ByteBuffer(OBJECT_HEADER_SIZE); bb.writeByte(MESSAGE_TYPE_REQUEST); bb.writeInt(lObject); bb.writeInt(lInstanceNumber); bb.writeInt(lStart); bb.writeInt(lLength); return bb.buffer; }; /** * Requests a command from a LaunchLike server with the given code. * @param {object} {lObject, lInstanceNumber} * @returns Nothing. This calls a function within the class context provided to it. */ const sendCommand = ({ lCommand, lInstanceNumber = 0 }, context) => { context.bytesToSend({ cData: getSendCommandData({ lCommand, lInstanceNumber, }), }); }; /** * Sends an object from a LaunchLike server with the given code and data. * @param {object} {lObject, lInstanceNumber, lStart, cData} * @returns Nothing. This calls a function within the class context provided to it. */ const sendObject = ( { lObject, lInstanceNumber = 0, lStart = 0, cData }, context ) => { context.bytesToSend({ cData: getSendObjectData({ lObject, lInstanceNumber, lStart, cData, }), }); }; /** * Requests an object from a LaunchLike server with the given code. * @param {object} {cData} - An object containing the request code, the instance number, the starting position, and the length. Generally only the data is provided. * @returns Nothing. This calls a function within the class context provided to it. */ const requestObject = ( { lObject, lInstanceNumber = 0, lStart = 0, lLength = 0 }, context ) => { context.bytesToSend({ cData: getRequestObjectData({ lObject, lInstanceNumber, lStart, lLength, }), }); }; /** * Takes a Tobject and parses out a message type definition and length for the data. * The function then calls a handler method of the context which was provided to it with the transcribed data. * @param {bytebuffer} cData - The data which you wish to decode * @param {class} context - The class context from which you're calling this function. * @returns Nothing. This calls a function within the class context provided to it. */ const processBytes = async (cData, context) => { if (!context) return; // What stage of byte processing the function is in. var processingState = 'idle'; var byteBufferInt; var byteBufferData; var cMessageType; var lObjectType; var lInstanceNumber; var lStart; var lLength; const discharge = ({ reason }, context) => { var lReceivedObjectType = lObjectType; var lReceivedInstanceNumber = lInstanceNumber; switch (cMessageType) { case MESSAGE_TYPE_REQUEST: { let lReceivedStart = lStart; let lReceivedLength = lLength; context.ObjectRequested({ lObject: lReceivedObjectType, lInstanceNumber: lReceivedInstanceNumber, lOffset: lReceivedStart, lLength: lReceivedLength, }); } break; case MESSAGE_TYPE_SEND: { const cData = [...byteBufferData.buffer]; const lReceivedStart = lStart; context.ObjectReceived({ lObject: lReceivedObjectType, lInstanceNumber: lReceivedInstanceNumber, lOffset: lReceivedStart, cData, }); break; } case MESSAGE_TYPE_COMMAND: { context.CommandReceived({ lCommand: lReceivedObjectType, lInstanceNumber, }); } break; default: console.log( 'Somehow an invalid data type in the discharge. Something is monumentally messed up' ); break; } processingState = 'idle'; return; }; cData.forEach((cByte, idx) => { if (processingState == 'idle') { cMessageType = cByte; // Check if cMessageType equals a valid message type if ( cMessageType == MESSAGE_TYPE_REQUEST || cMessageType == MESSAGE_TYPE_SEND || cMessageType == MESSAGE_TYPE_COMMAND ) { // Change the processing state processingState = 'objectNo'; byteBufferInt = new ByteBuffer(SIZEOF_INT); return; } else { console.log(`Invalid MESSAGE_TYPE`); return; } return; } if (processingState == 'objectNo') { byteBufferInt.writeByte(cByte); // Once all slots in the byte buffer are occupied, move to next state if (byteBufferInt.offset == byteBufferInt.limit) { // Store object type lObjectType = helperFunctions.intFromBytes([...byteBufferInt.buffer]); // reset byteBufferInt byteBufferInt = new ByteBuffer(SIZEOF_INT); processingState = 'instanceNo'; return; } return; } if (processingState == 'instanceNo') { byteBufferInt.writeByte(cByte); if (byteBufferInt.offset == byteBufferInt.limit) { // Store the instance number lInstanceNumber = helperFunctions.intFromBytes([ ...byteBufferInt.buffer, ]); // Reset byteBufferInt byteBufferInt = new ByteBuffer(SIZEOF_INT); // Decide what to do depending on message type. if (cMessageType == MESSAGE_TYPE_COMMAND) { discharge({ reason: 'command' }, context); return; } processingState = 'start'; return; } return; } if (processingState == 'start') { byteBufferInt.writeByte(cByte); if (byteBufferInt.offset == byteBufferInt.limit) { // Store the start position lStart = helperFunctions.intFromBytes([...byteBufferInt.buffer]); // Reset byteBufferInt byteBufferInt = new ByteBuffer(SIZEOF_INT); processingState = 'length'; return; } return; } if (processingState == 'length') { // 0, 0, 4, 75 byteBufferInt.writeByte(cByte); if (byteBufferInt.offset == byteBufferInt.limit) { // Store the length lLength = helperFunctions.intFromBytes([...byteBufferInt.buffer]); // Reset byteBufferInt byteBufferInt = new ByteBuffer(SIZEOF_INT); // Allocate length for data or Discharge, if no data payload if (cMessageType == MESSAGE_TYPE_REQUEST) { discharge({ reason: 'request' }, context); return; } byteBufferData = new ByteBuffer(lLength); processingState = 'data'; return; } return; } if (processingState == 'data') { byteBufferData.writeByte(cByte); // Once chunk of data is fully processed, discharge if (byteBufferData.offset == byteBufferData.limit) { discharge({ reason: 'data finished' }, context); return; } return; } return; }); }; module.exports.smokeSignal = { getSendObjectData, getSendCommandData, getRequestObjectData, sendCommand, sendObject, requestObject, processBytes, }; module.exports.constants = { OBJECT_HEADER_SIZE, COMMAND_HEADER_SIZE, MESSAGE_TYPE_REQUEST, MESSAGE_TYPE_SEND, MESSAGE_TYPE_COMMAND, SIZEOF_INT, }; </code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.10</a> on Thu May 19 2022 14:49:34 GMT-0400 (Eastern Daylight Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/polyfill.js"></script> <script src="scripts/linenumber.js"></script> <script src="scripts/search.js" defer></script> <script src="scripts/collapse.js" defer></script> </body> </html>