mikronode-ng
Version:
Mikrotik API implemented in Node
479 lines (332 loc) • 22.4 kB
HTML
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
<meta property="og:title" content=""/>
<meta property="og:type" content="website"/>
<meta property="og:image" content=""/>
<meta property="og:url" content=""/>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<script src="scripts/jquery.min.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-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/bootstrap.min.css">
<link type="text/css" rel="stylesheet" href="styles/jaguar.css">
<script>
var config = {"monospaceLinks":true,"cleverLinks":true,"default":{"outputSourceFiles":true},"applicationName":"MikroNode","disqus":"","googleAnalytics":"","openGraph":{"title":"","type":"website","image":"","site_name":"","url":""},"meta":{"title":"","description":"","keyword":""},"linenums":false};
</script>
</head>
<body>
<div id="wrap" class="clearfix">
<div class="navigation">
<h3 class="applicationName"><a href="index.html">MikroNode</a></h3>
<div class="search">
<input id="search" type="text" class="form-control input-sm" placeholder="Search Documentations">
</div>
<ul class="list">
<li class="item" data-name="mikronode-ng">
<span class="title">
<a href="mikronode-ng.html">mikronode-ng</a>
<span class="static">static</span>
</span>
<ul class="members itemMembers">
</ul>
<ul class="typedefs itemMembers">
</ul>
<ul class="methods itemMembers">
<span class="subtitle">Methods</span>
<li data-name="mikronode-ng.getConnection"><a href="mikronode-ng.html#.getConnection">getConnection</a></li>
<li data-name="mikronode-ng.parseItems"><a href="mikronode-ng.html#.parseItems">parseItems</a></li>
</ul>
<ul class="events itemMembers">
</ul>
</li>
<li class="item" data-name="mikronode-ng.Channel">
<span class="title">
<a href="mikronode-ng.Channel.html">mikronode-ng.Channel</a>
</span>
<ul class="members itemMembers">
<span class="subtitle">Members</span>
<li data-name="mikronode-ng.Channel#clearEvents"><a href="mikronode-ng.Channel.html#clearEvents">clearEvents</a></li>
<li data-name="mikronode-ng.Channel#closed"><a href="mikronode-ng.Channel.html#closed">closed</a></li>
<li data-name="mikronode-ng.Channel#closeOnDone"><a href="mikronode-ng.Channel.html#closeOnDone">closeOnDone</a></li>
<li data-name="mikronode-ng.Channel#closing"><a href="mikronode-ng.Channel.html#closing">closing</a></li>
<li data-name="mikronode-ng.Channel#id"><a href="mikronode-ng.Channel.html#id">id</a></li>
<li data-name="mikronode-ng.Channel#lastCommand"><a href="mikronode-ng.Channel.html#lastCommand">lastCommand</a></li>
<li data-name="mikronode-ng.Channel#running"><a href="mikronode-ng.Channel.html#running">running</a></li>
<li data-name="mikronode-ng.Channel#saveBuffer"><a href="mikronode-ng.Channel.html#saveBuffer">saveBuffer</a></li>
</ul>
<ul class="typedefs itemMembers">
<span class="subtitle">Typedefs</span>
<li data-name="mikronode-ng.Channel.writeCallback"><a href="mikronode-ng.Channel.html#.writeCallback">writeCallback</a></li>
</ul>
<ul class="methods itemMembers">
<span class="subtitle">Methods</span>
<li data-name="mikronode-ng.Channel#close"><a href="mikronode-ng.Channel.html#close">close</a></li>
<li data-name="mikronode-ng.Channel#finalize"><a href="mikronode-ng.Channel.html#finalize">finalize</a></li>
<li data-name="mikronode-ng.Channel#write"><a href="mikronode-ng.Channel.html#write">write</a></li>
</ul>
<ul class="events itemMembers">
<span class="subtitle">Events</span>
<li data-name="mikronode-ng.Channel#event:close"><a href="mikronode-ng.Channel.html#event:event:close">event:close</a></li>
<li data-name="mikronode-ng.Channel#event:done"><a href="mikronode-ng.Channel.html#event:event:done">event:done</a></li>
<li data-name="mikronode-ng.Channel#event:error"><a href="mikronode-ng.Channel.html#event:event:error">event:error</a></li>
<li data-name="mikronode-ng.Channel#event:timeout"><a href="mikronode-ng.Channel.html#event:event:timeout">event:timeout</a></li>
<li data-name="mikronode-ng.Channel#event:trap"><a href="mikronode-ng.Channel.html#event:event:trap">event:trap</a></li>
</ul>
</li>
<li class="item" data-name="mikronode-ng.Connection">
<span class="title">
<a href="mikronode-ng.Connection.html">mikronode-ng.Connection</a>
</span>
<ul class="members itemMembers">
<span class="subtitle">Members</span>
<li data-name="mikronode-ng.Connection#channels"><a href="mikronode-ng.Connection.html#channels">channels</a></li>
<li data-name="mikronode-ng.Connection#closeOnDone"><a href="mikronode-ng.Connection.html#closeOnDone">closeOnDone</a></li>
<li data-name="mikronode-ng.Connection#host"><a href="mikronode-ng.Connection.html#host">host</a></li>
<li data-name="mikronode-ng.Connection#password"><a href="mikronode-ng.Connection.html#password">password</a></li>
<li data-name="mikronode-ng.Connection#port"><a href="mikronode-ng.Connection.html#port">port</a></li>
<li data-name="mikronode-ng.Connection#status"><a href="mikronode-ng.Connection.html#status">status</a></li>
<li data-name="mikronode-ng.Connection#timeout"><a href="mikronode-ng.Connection.html#timeout">timeout</a></li>
<li data-name="mikronode-ng.Connection#tls"><a href="mikronode-ng.Connection.html#tls">tls</a></li>
<li data-name="mikronode-ng.Connection#user"><a href="mikronode-ng.Connection.html#user">user</a></li>
</ul>
<ul class="typedefs itemMembers">
<span class="subtitle">Typedefs</span>
<li data-name="mikronode-ng.Connection.connectCallback"><a href="mikronode-ng.Connection.html#.connectCallback">connectCallback</a></li>
</ul>
<ul class="methods itemMembers">
<span class="subtitle">Methods</span>
<li data-name="mikronode-ng.Connection.parseItems"><a href="mikronode-ng.Connection.html#.parseItems">parseItems</a></li>
<li data-name="mikronode-ng.Connection#closeChannel"><a href="mikronode-ng.Connection.html#closeChannel">closeChannel</a></li>
<li data-name="mikronode-ng.Connection#connect"><a href="mikronode-ng.Connection.html#connect">connect</a></li>
<li data-name="mikronode-ng.Connection#getChannel"><a href="mikronode-ng.Connection.html#getChannel">getChannel</a></li>
<li data-name="mikronode-ng.Connection#getCommandPromise"><a href="mikronode-ng.Connection.html#getCommandPromise">getCommandPromise</a></li>
<li data-name="mikronode-ng.Connection#getConnectPromise"><a href="mikronode-ng.Connection.html#getConnectPromise">getConnectPromise</a></li>
<li data-name="mikronode-ng.Connection#openChannel"><a href="mikronode-ng.Connection.html#openChannel">openChannel</a></li>
</ul>
<ul class="events itemMembers">
<span class="subtitle">Events</span>
<li data-name="mikronode-ng.Connection#event:close"><a href="mikronode-ng.Connection.html#event:event:close">event:close</a></li>
<li data-name="mikronode-ng.Connection#event:error"><a href="mikronode-ng.Connection.html#event:event:error">event:error</a></li>
<li data-name="mikronode-ng.Connection#event:timeout"><a href="mikronode-ng.Connection.html#event:event:timeout">event:timeout</a></li>
<li data-name="mikronode-ng.Connection#event:trap"><a href="mikronode-ng.Connection.html#event:event:trap">event:trap</a></li>
</ul>
</li>
<li class="item" data-name="mikronode-ng.Trap">
<span class="title">
<a href="mikronode-ng.Trap.html">mikronode-ng.Trap</a>
</span>
<ul class="members itemMembers">
<span class="subtitle">Members</span>
<li data-name="mikronode-ng.Trap#channel"><a href="mikronode-ng.Trap.html#channel">channel</a></li>
<li data-name="mikronode-ng.Trap#channelId"><a href="mikronode-ng.Trap.html#channelId">channelId</a></li>
<li data-name="mikronode-ng.Trap#errors"><a href="mikronode-ng.Trap.html#errors">errors</a></li>
</ul>
<ul class="typedefs itemMembers">
</ul>
<ul class="methods itemMembers">
</ul>
<ul class="events itemMembers">
</ul>
</li>
<li class="item" data-name="mikronode-ng.TrapError">
<span class="title">
<a href="mikronode-ng.TrapError.html">mikronode-ng.TrapError</a>
</span>
<ul class="members itemMembers">
<span class="subtitle">Members</span>
<li data-name="mikronode-ng.TrapError#category"><a href="mikronode-ng.TrapError.html#category">category</a></li>
<li data-name="mikronode-ng.TrapError#message"><a href="mikronode-ng.TrapError.html#message">message</a></li>
</ul>
<ul class="typedefs itemMembers">
</ul>
<ul class="methods itemMembers">
</ul>
<ul class="events itemMembers">
</ul>
</li>
</ul>
</div>
<div class="main">
<h1 class="page-title" data-filename="index.html">Index</h1>
<h3> </h3>
<section>
<article class="readme"><h1>MikroNode</h1><p> Full-Featured asynchronous Mikrotik API interface for <a href="http://nodejs.org">NodeJS</a>.</p>
<pre class="prettyprint source"><code> var MikroNode = require('mikronode-ng');
var connection = MikroNode.getConnection(process.argv[2], process.argv[3], process.argv[4]);
connection.connect(function(conn) {
var chan = conn.openChannel();
conn.closeOnDone = true;
chan.write('/ip/address/print', function() {
chan.closeOnDone = true;
chan.on('done', function(data) {
var parsed = MikroNode.parseItems(data);
parsed.forEach(function(item) {
console.log('Interface/IP: ' + item.interface + "/" + item.address);
});
});
chan.once('trap', function(trap, chan) {
console.log('Command failed: ' + trap);
});
chan.once('error', function(err, chan) {
console.log('Oops: ' + err);
});
});
});
/* Now let's do this with Promises */
var connection = MikroNode.getConnection(process.argv[2], process.argv[3], process.argv[4], {
closeOnDone : true
});
connection.getConnectPromise().then(function(conn) {
conn.getCommandPromise('/ip/address/print').then(function resolved(values) {
console.log('Addreses: ' + JSON.stringify(values));
}, function rejected(reason) {
console.log('Oops: ' + JSON.stringify(reason));
});
});</code></pre><h2>Installation</h2><p> Clone this repository into your node_modules directory.</p>
<ul>
<li>or -<br> $ npm install mikronode-ng</li>
</ul>
<h2>Features</h2><ul>
<li>Channel based communication</li>
<li>Multiple Connections can be used in parallel in the same Node process</li>
<li>Multiple Channels can be used in parallel on the same Connection</li>
<li>Synchronous execution of commands issued on the same channel</li>
<li>Asynchrounous execution of commands issued on different channels</li>
<li>Focus on high performance</li>
<li>ES6 Promise support for Connection and Channel</li>
<li>TLS Support</li>
</ul>
<h2>Upgrading from versions < 1.0.0</h2><p>There are 2 changes that will need to be made...</p>
<pre class="prettyprint source"><code>var MikroNode = require('mikronode-ng');
// From
var connection = new MikroNode(...)
// To
var connection = MikroNode.getConnection(...)
// or
var connection = new MikroNode.Connection(...)
// From
connection.closeOnDone(true);
channel.closeOnDone(true);
// To
connection.closeOnDone = true;
channel.closeOnDone = true;</code></pre><p>Everything else should work as expected.</p>
<h2>TODO</h2><ul>
<li>???</li>
</ul>
<h2>API</h2><p>See the <a href="http://trakkasure.github.io/mikronode">API JSDocs</a> in the doc directory.</p>
<h2>Notes for Node < 4.0.0</h2><p>MikroNode requires 2 ES6 features that appeared in Node 4.0.0: Promises and WeakMaps. If<br>you're running an earlier version of Node and MikroNode can't find those symbols, it will<br>attempt to load them from the 'es6-promise' and 'weakmap' packages respectively. If you wish<br>to use other packages to supply those symbols, require them before requiring mikronode and<br>set the global symbols.</p>
<pre class="prettyprint source"><code>global.WeakMap = require('some-weakmap-polyfill').WeakMap;
global.Promise = require('some-promise-polyfill').Promise;
var MikroNode = require('mikronode-ng');</code></pre><h2>Tests</h2><p>The <a href="test/">test</a> directory contains a test that exercises all functionality including<br>Promises and listens/cancels.</p>
<h2>Examples</h2><p><a href="examples/">Examples (including Promise examples)</a></p>
<h3>Connect to a Mikrotik, and add an address to ether1</h3><pre class="prettyprint source"><code>var MikroNode = require('mikronode-ng');
var connection = MikroNode.getConnection('192.168.88.1','admin','password');
connection.closeOnDone = true;
connection.connect(function(conn) {
var chan=conn.openChannel();
chan.closeOnDone = true;
chan.write(['/ip/address/add','=interface=ether1','=address=192.168.1.1'], function(c) {
c.on('trap',function(data) {
console.log('Error setting IP: '+data);
});
c.on('done',function(data) {
console.log('IP Set.');
});
});
});</code></pre><h3>Writing the program for the example API conversation on the <a href="http://wiki.mikrotik.com/wiki/API#.2Fcancel.2C_simultaneous_commands">Mikrotik Wiki</a></h3><p>DON'T RUN THIS IF YOU'RE CONNECTED VIA ether1! :)</p>
<pre class="prettyprint source"><code> var MikroNode = require('mikronode-ng');
var connection = MikroNode.getConnection('192.168.88.1','admin','password');
connection.connect(function(conn) {
conn.closeOnDone = true;
var chan2=conn.openChannel(2);
chan2.write('/interface/listen',function(chan) {
chan.on('read',function(data) {
packet=MikroNode.parseItems(data);
console.log('Interface change: '+JSON.stringify(packet));
});
});
var chan3=conn.openChannel(3);
chan3.closeOnDone = true
chan3.write(['/interface/set','=disabled=yes','=.id=ether1'],function(chan) {
chan.on('done',function(d,chan) {
// We do this here, 'cause we want channel 4 to write after channel 3 is done.
var chan4=conn.openChannel(4); // We'll use this later.
chan4.closeOnDone = true;
chan4.write(['/interface/set','=disabled=no','=.id=ether1'],function() {
var chan5=conn.openChannel(5);
chan5.closeOnDone = true;
chan5.write('/interface/getall',function(chan) {
chan.on('done',function(data) {
packets=MikroNode.parseItems(data);
packets.forEach(function(packet) {
console.log('Interface: '+JSON.stringify(packet));
});
chan2.close(); // This should call the /cancel command to stop the listen.
});
});
})
});
});
});</code></pre><h3>Simplifying the above by reducing the number of channels.</h3><p>DON'T RUN THIS IF YOU'RE CONNECTED VIA ether1! :)<br> Notice how the callback embedding is not needed using the syncronous capability.</p>
<pre class="prettyprint source"><code> var MikroNode = require('mikronode-ng');
var connection = MikroNode.getConnection('192.168.88.1','admin','password');
connection.connect(function(conn) {
conn.closeOnDone = true; // All channels need to complete before the connection will close.
var listenChannel=conn.openChannel();
listenChannel.write('/interface/listen',function(chan) {
chan.on('read',function(data) {
packet=MikroNode.parseItems(data);
console.log('Interface change: '+JSON.stringify(packet));
});
});
var actionChannel=conn.openChannel();
// These will run synchronsously
actionChannel.write(['/interface/set','=disabled=yes','=.id=ether1']); // don't care to do anything after it's done.
actionChannel.write(['/interface/set','=disabled=no','=.id=ether1']); // don't care to do anything after it's done.
actionChannel.write('/interface/getall',function(chan) {
chan.on('done',function(data) {
packets=MikroNode.parseItems(data);
packets.forEach(function(packet) {
console.log('Interface: '+JSON.stringify(packet));
});
listenChannel.close(); // This should call the /cancel command to stop the listen.
});
});
actionChannel.close(); // The above commands will complete before this is closed.
});</code></pre><h3>A simple Promise scenario</h3><pre class="prettyprint source"><code>// If your nodejs installation doesn't have Promise support, uncomment
// the following line
//require('es6-promise').polyfill();
// or globally export Promise from your favorite ES6 compatable Promise library.
var MikroNode = require('mikronode-ng');
var connection = MikroNode.getConnection(process.argv[2], process.argv[3], process.argv[4], {
closeOnDone : true
});
connection.getConnectPromise().then(function(conn) {
conn.getCommandPromise('/ip/address/print').then(function resolved(values) {
console.log('Addreses: ' + JSON.stringify(values));
}, function rejected(reason) {
console.log('Oops: ' + JSON.stringify(reason));
});
});</code></pre><p> The methods <em>decodeLength</em> and <em>encodeString</em> were written based on code <a href="http://wiki.mikrotik.com/wiki/API_PHP_class#Class">here on the Mikrotik Wiki</a>.</p>
<h2>License</h2><p>(The MIT License)</p>
<p>Copyright (c) 2011-2015 Brandon Myers <a href="mailto:trakkasure@gmail.com">trakkasure@gmail.com</a><br>Copyright (c) 2015 George Joseph <a href="mailto:george.joseph@fairview5.com">george.joseph@fairview5.com</a></p>
<p>Permission is hereby granted, free of charge, to any person obtaining<br>a copy of this software and associated documentation files (the<br>'Software'), to deal in the Software without restriction, including<br>without limitation the rights to use, copy, modify, merge, publish,<br>distribute, sublicense, and/or sell copies of the Software, and to<br>permit persons to whom the Software is furnished to do so, subject to<br>the following conditions:</p>
<p>The above copyright notice and this permission notice shall be<br>included in all copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,<br>EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.<br>IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY<br>CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,<br>TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE<br>SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p></article>
</section>
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Wed Jul 06 2016 06:45:18 GMT-0600 (MDT)
</footer>
</div>
</div>
<script>prettyPrint();</script>
<script src="scripts/linenumber.js"></script>
<script src="scripts/main.js"></script>
</body>
</html>