Coder Social home page Coder Social logo

mikronode's Introduction

Mikronode

Full-Featured asynchronous Mikrotik API interface for NodeJS.

    var MikroNode = require('mikronode');
    
    var device = new MikroNode('192.168.0.1');

    device.connect()
      .then(([login])=>{
        return login('username','password');
      })
      .then(function(conn) {

        var chan=conn.openChannel("addresses"); // open a named channel
        var chan2=conn.openChannel("firewall_connections",true); // open a named channel, turn on "closeOnDone"

        chan.write('/ip/address/print');

        chan.on('done',function(data) {

             // data is all of the sentences in an array.
             data.forEach(function(item) {
                console.log('Interface/IP: '+item.data.interface+"/"+item.data.address);
             });

             chan.close(); // close the channel. It is not autoclosed by default.
             conn.close(); // when closing connection, the socket is closed and program ends.

        });

        chan2.write('/ip/firewall/print');

        chan2.done.subscribe(function(data){

             // data is all of the sentences in an array.
             data.forEach(function(item) {
                var data = MikroNode.resultsToObj(item.data); // convert array of field items to object.
                console.log('Interface/IP: '+data.interface+"/"+data.address);
             });

        });

    });

Installation

Clone this repository into your node_modules directory.

  • or - $ npm install mikronode

Features

  • Channel based communication
  • Multiple channels can be used at once.
  • Synchronous execution of commands issued on the same channel.
  • Asynchrounous execution of commands issued on different channels.
  • Focus on high performance

TODO

  • Write tests con make sure everything keeps working whenever making changes.

API

    // There are 2 ways to get resulting data from channels:
    // Using events, like earlier versions:
    //   data takes each sentence one at a time.
    //   done takes an entire result from last command.
    // Using Streams channel and connection provides access to several layers of them.
    //   Channels filter only data for that channel
    //      data: sentences that are data.
    //      trap: stream of traps. Useful for reading data streams using takeUntil(trapStream). Or for piping to notification on UI.
    //      bufferedSteam: when data response is "done" the buffered stream emits packets. Don't use this with a "listen" command.
    //      read: every sentence passes through this one.
    //   Connections also have streams, where they do not filter per channel:
    //      raw: The raw socket data. This emits buffers.
    //      sentence:each raw sentence is emitted from this stream
    //      read: the parsed sentences this is similar to the Channel read stream except does not filter by channel id.
    //      trap: all traps

Connection

Calling new MikroNode(host[,port,socketTimeout]) returns an object representing the device.

    var MikroNode = require('mikronode');
    var Device =new MikroNode(host,port);
    Device.connect().then(([login])=>login('admin','password')).then(function(conn) { 
        var chan=conn.openChannel();
    });

With the above code, the following is API description. conn is Connection object, chan is Channel object.

  • MikroNode.resultsToObj(dataObj) <Object|Array> Convert the sentence format of the mikrotik into a more easily readable
  • Device.connect([cb]) Connect to the target device. The optional callback function is called after successful connect with the function to call to login as the 2nd parameter, and any connection errors as the first. the connect method returns a Promise that is resolved when connecting.
  • Device.socketOpts (write-only property) Optionally allows the setting of parameters that the socket connecting to the mikrotik will use.
  • Device.TLS(tlsOpts) Enable TLS and set it's options. Take note that you will need to be sure the port the API is trying to connect is an SSL/TLS port. For unauthenticated SSL connections (no signed certs) only ADH cipher is supported. This is a limitation of the RouterOS software
  • Device.setDebug(level) Set the default debug logging level for the device, and all subsequent created connections.
  • conn.openChannel(id|name) Open and return a new channel object. Each channel is a unique command line to the mikrotik, allowing simultaneous execution of commands. The ID parameter is optional. If not specified, the current timestamp is used. If too many channels are opened at one time without specifying a name, there could be duplicate names. * conn.connected() Returns true is currently connected to a mikrotik device.
  • conn.closeChannel(id)
    Closes an open channel. This will call the close method of the channel object.
  • conn closeOnDone(b)
    If b == true, when a done event occurs, close the connection after all channels have been closed.
  • conn.close(force)
    Close the connection. If force is true, force close of any open channels then close this connection.
  • conn.getHost()
  • conn.getUser()

Channel

The following property/methods are available for channels:

  • channel.done "done" is the stream that contains events when the done sentence comes from the device. When subscribing, the stream's data contans an object with each line received in an array.
  • channel.data For each sentence received, this has an observable event. Only sentences designated for this channel will pass through this sentence. This is handy when following trailing output from a listen command, where the data could be endless.
  • channel.trap Any traps that occur on a channel can be captured in this observable stream.
  • channel.sync(b) If b == true, each command is run synchronously. Otherwise commands are executed as they are passed.
  • channel.closeOnDone(b) If b == true, when a done event occurs, close the channel after all commands queued have been executed.
  • channel.getId()
  • channel.write(lines[,optionsObject]) Returns a promise that is resolved when the command sent is complete and is "done" The promise is rejected if a trap or fatal error occurs. Lines can be a string, or an array of strings. If it is a string, then it is split on the EOL character and each resulting line is sent as a separate word (in API speak) If lines is an array, then each element is sent unaltered. If lines is a string and optionsObject is provided, the optionsObject is converted to standard sentence output: =propertyName=propertyValue
  • channel.close(force) Close the channel. If there are any commands still waiting to be executed, they will be completed before closing the channel.
    If force is TRUE, then the channel is immediately closed. If the channel is running, the cancel command is sent to stop any running listen commands, or potentially long running output.

Examples

Connect to a Mikrotik, and add an address to ether1

     var api = require('mikronode');

     var device = new api('192.168.0.1');
     device.connect().then(([login])=>login('admin','password')).then(function(conn) {

        var chan=conn.openChannel();

        chan.write('/ip/address/add',{'interface':'ether1','address':'192.168.1.1'});
        chan.on('trap',function(data) {
            console.log('Error setting IP: '+data);
        });
        chan.on('done',function(data) {
            console.log('IP Set.');
        });
        chan.close();
        conn.close();
     });

Writing the program for the example API conversation on the Mikrotik Wiki

     var MikroNode = require('mikronode');

     var device = new MikroNode('192.168.0.1');
     device.connect().then(([login])=>login('admin','password')).then(function(conn) {
        conn.closeOnDone(true); // when all channels are "done" the connection should close.

        var chan1=conn.openChannel("interface_listener");
        chan1.write('/interface/listen');
        chan1.data.subscribe(function(item) {
            var packet=MikroNode.resultsToObj(item.data);
            console.log('Interface change: '+JSON.stringify(packet));
        });

        // This should be called when the cancel is called below. (trap occurs first, then done)
        chan1.done.subscribe(function(packet) {
            // This should output everything that the above outputted.
            packet.data.forEach(function(data) {
                var packets=MikroNode.resultsToObj(data);
                console.log('Interface: '+JSON.stringify(packet));
            });
        });

        var chan2=conn.openChannel('config_interface');

        // added closeOnDone option to this call
        var chan3=conn.openChannel('enable_interface'); // We'll use this later.

        var chan4=conn.openChannel('getall_interfaces'); 

        chan2.write('/interface/set',{'disabled':'yes','.id':'ether1'});
        chan2.done.subscribe(function(items) {
            // We do this here, 'cause we want channel 4 to write after channel 3 is done.
            // No need to listen for channel3 to complete if we don't care.
            chan3.write('/interface/set',{'disabled':'no','.id':'ether1'});

            chan4.write('/interface/getall');

            // Alternative (legacy) way of caturing when chan4 is done.
            chan4.on('done',function(packet) {
                packet.data.forEach(function(data) {
                    var packets=MikroNode.resultsToObj(data);
                    console.log('Interface: '+JSON.stringify(packet));
                });
                chan1.close(); // This should call the /cancel command to stop the listen.
            });
        });
    });

Simplifying the above by reducing the number of channels.

Notice how the callback embedding is not needed using the syncronous capability.

    var MikroNode = require('mikronode');

    var device = new MikroNode('192.168.0.1');
     device.connect().then(([login])=>login('admin','password')).then(function(conn) {
        conn.closeOnDone(true); // All channels need to complete before the connection will close.
        var listenChannel=conn.openChannel();
        listenChannel.write('/interface/listen');

        // Each sentence that comes from the device goes through this.
        listenChannel.read.subscribe(function(data) {
            var packet=MikroNode.resultsToObj(data);
            console.log('Interface change: '+JSON.stringify(packet));
        });

        var actionChannel=conn.openChannel();
        actionChannel.sync(true);

        // These will run synchronsously
        actionChannel.write('/interface/set',{'disabled':'yes','.id':'ether1'});
        actionChannel.write('/interface/set',{'disabled':'no','.id':'ether1'});
        actionChannel.write('/interface/getall');
        actionChannel.on('done',function(packet) {
            packet.data.forEach(function(data) {
                var packets=MikroNode.resultsToObj(data);
                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.
    });

Promises add simplicity:

    var MikroNode = require('mikronode');
    var device = new MikroNode('192.168.0.1');
    device.connect().then(([login])=>login('admin','password')).then(function(conn) {
        console.log("Logged in.");
        conn.closeOnDone(true); // All channels need to complete before the connection will close.
        var listenChannel=conn.openChannel("listen");

        // Each sentence that comes from the device goes through the data stream.
        listenChannel.data.subscribe(function(data) {
            // var packet=MikroNode.resultsToObj(data);
            console.log('Interface change: ',JSON.stringify(data));
        },error=>{
            console.log("Error during listenChannel subscription",error) // This shouldn't be called.
        },()=>{
            console.log("Listen channel done.");
        });

        // Tell our listen channel to notify us of changes to interfaces.
        listenChannel.write('/interface/listen').then(result=>{
            console.log("Listen channel done promise.",result);
        })
        // Catch shuold be called when we call /cancel (or listenChannel.close())
        .catch(error=>console.log("Listen channel rejection:",error));

        // All our actions go through this.
        var actionChannel=conn.openChannel("action",false); // don't close on done... because we are running these using promises, the commands complete before each then is complete.

        // Do things async. This is to prove that promises work as expected along side streams.
        actionChannel.sync(false);
        actionChannel.closeOnDone(false); // Turn off closeOnDone because the timeouts set to allow the mikrotik to reflect the changes takes too long. The channel would close.

        // These will run synchronsously (even though sync is not set to true)
        console.log("Disabling interface");
        actionChannel.write('/interface/set',{'disabled':'yes','.id':'ether1'}).then(results=>{
            console.log("Disable complete.");
            // when the first item comes in from the listen channel, it should send the next command.
            const {promise,resolve,reject}=MikroNode.getUnwrappedPromise();
            listenChannel.data
                .take(1)
                // This is just to prove that it grabbed the first one.
                .do(d=>console.log("Data:",MikroNode.resultsToObj(d.data)))
                .subscribe(d=>actionChannel.write('/interface/set',{'disabled':'no','.id':'ether1'}).then(resolve,reject));
            return promise;
        })
        .then(results=>{
            console.log("Enabled complete.");
            // return new Promise((r,x)=>setTimeout(r,1000)).then(()=>actionChannel.write('/interface/getall'));
            const {promise,resolve,reject}=MikroNode.getUnwrappedPromise();
            // when the second item comes in from the listen channel, it should send the next command.
            listenChannel.data
                .take(1)
                // This is just to prove that it grabbed the second one.
                .do(d=>console.log("Data:",MikroNode.resultsToObj(d.data)))
                .subscribe(d=>actionChannel.write('/interface/getall').then(resolve,reject));
            return promise;
        })
        .then(results=>{
            var formatted=MikroNode.resultsToObj(results.data);
            var columns=[".id","name","mac-address","comment"];
            var filtered=formatted.map(line=>columns.reduce((p,c)=>{p[c]=line[c];return p},{}));
            console.log('Interface [ID,Name,MAC-Address]: ',JSON.stringify(filtered,true,4));
        })
        .catch(error=>{
            console.log("An error occurred during one of the above commands: ",error);
        })
        // This runs after all commands above, or if an error occurs.
        .then(nodata=>{
            console.log("Closing everything.");
            listenChannel.close(true); // This should call the /cancel command to stop the listen.
            actionChannel.close();
        });
    });

The methods decodeLength and encodeString were written based on code here on the Mikrotik Wiki.

License

(The MIT License)

Copyright (c) 2011,2012,2013,2014,2015,2016,2017 Brandon Myers [email protected]

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.

mikronode's People

Contributors

azerothian avatar feute avatar filipchalupa avatar gtjoseph avatar trakkasure avatar xeleniumz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mikronode's Issues

Printing arp produces an error

channel.write('/ip/arp/print')

***************************************************************************
***************************************************************************
Error processing sentence: { SyntaxError: Expected [.a-z\-0-9] but "D" found.
    at peg$buildStructuredError (/Users/subash/Projects/lan-manager/node_modules/mikronode/dist/mikronode.js:2166:13)
    at Object.peg$parse [as parse] (/Users/subash/Projects/lan-manager/node_modules/mikronode/dist/mikronode.js:3193:12)
    at MapSubscriber.project (/Users/subash/Projects/lan-manager/node_modules/mikronode/dist/mikronode.js:478:39)
    at MapSubscriber._next (/Users/subash/Projects/lan-manager/node_modules/rxjs/operators/map.js:79:35)
    at MapSubscriber.Subscriber.next (/Users/subash/Projects/lan-manager/node_modules/rxjs/Subscriber.js:93:18)
    at MapSubscriber._next (/Users/subash/Projects/lan-manager/node_modules/rxjs/operators/map.js:85:26)
    at MapSubscriber.Subscriber.next (/Users/subash/Projects/lan-manager/node_modules/rxjs/Subscriber.js:93:18)
    at DoSubscriber._next (/Users/subash/Projects/lan-manager/node_modules/rxjs/operators/tap.js:88:30)
    at DoSubscriber.Subscriber.next (/Users/subash/Projects/lan-manager/node_modules/rxjs/Subscriber.js:93:18)
    at Subject.next (/Users/subash/Projects/lan-manager/node_modules/rxjs/Subject.js:55:25)
  message: 'Expected [.a-z\\-0-9] but "D" found.',
  expected:
   [ { type: 'class',
       parts: [Array],
       inverted: false,
       ignoreCase: false } ],
  found: 'D',
  location:
   { start: { offset: 164, line: 9, column: 2 },
     end: { offset: 165, line: 9, column: 3 } },
  name: 'SyntaxError' }
Skipping and continuing

Mikronode with Express Js: TypeError: _sentence$.get(…).do is not a function

I want to use Mikronode with Express Js but get an error TypeError: _sentence$.get(...).do is not a function for the first run.

I generate the application skeleton using Express generator and try the example Mikronode code from wiki.mikrotik.com

This is the code:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var api = require('mikronode');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// Mikronode example code
var connection = new api('192.168.0.1','admin','password');
connection.connect(function(conn) {

   var chan=conn.openChannel();

   chan.write('/ip/address/print',function() {
      chan.on('done',function(data) {

         var parsed = api.parseItems(data);

         parsed.forEach(function(item) {
            console.log('Interface/IP: '+item.interface+"/"+item.address);
         });

         chan.close();
         conn.close();

      });
   });
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};

    // render the error page
    res.status(err.status || 500);
    res.render('error');
});

module.exports = app;

If i run the code above, the output show an error:

/Users/me/Desktop/mknode/node_modules/mikronode/dist/mikronode.js:474
                _parsed$.set(this, _sentence$.get(this).do(function (d) {
                                                          ^

TypeError: _sentence$.get(...).do is not a function
    at new SocketStream (/Users/me/Desktop/mknode/node_modules/mikronode/dist/mikronode.js:474:52)
    at MikroNode.connect (/Users/me/Desktop/mknode/node_modules/mikronode/dist/mikronode.js:330:30)
    at Object.<anonymous> (/Users/me/Desktop/mknode/app.js:31:12)
    at Module._compile (module.js:643:30)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)
    at Module.require (module.js:587:17)
    at require (internal/module.js:11:18)
error Command failed with exit code 1.

My package.json:

{
  "name": "mknode",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "core-decorators": "^0.20.0",
    "debug": "~2.6.9",
    "express": "~4.16.0",
    "http-errors": "~1.6.2",
    "mikronode": "^2.3.11",
    "morgan": "~1.9.0",
    "pug": "2.0.0-beta11",
    "rxjs": "^6.2.2"
  }
}

Anyone can help me to solve this?

Uncaught Exception

I got strange behaviour. I have been using mikronode v0.3.3 from npm.
I have few applications that has the same code:

var connection = new mikrotik(ip, login, pass); connection.connect(function(conn) { var chan = conn.openChannel(); ... }

They work fine, but sometime some application stopped working with an error (see below).
The same code in other applications continues to work.
It crashes when openChannel() is called.

1 Apr 09:11:52 - [red] Uncaught Exception: 1 Apr 09:11:52 - Error: Uncaught, unspecified "error" event. (Timeout Connecting to host) at Connection.emit (events.js:157:17) at null.<anonymous> (/Users/Bladerunner/.node-red/node_modules/node-red-contrib-mikrotik/node_modules/mikronode/lib/index.js:458:55) at emitTwo (events.js:100:13) at emit (events.js:185:7) at Socket.<anonymous> (/Users/Bladerunner/.node-red/node_modules/node-red-contrib-mikrotik/node_modules/mikronode/lib/index.js:341:18) at Socket.g (events.js:273:16) at emitNone (events.js:80:13) at Socket.emit (events.js:179:7) at Socket._onTimeout (net.js:326:8) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5)

ERROR: Can't resolve 'dgram' in ...

dgram has been deprecated
https://www.npmjs.com/package/dgram

Node: v10.15.1
NPM: 6.4.1

ERROR in ./node_modules/native-dns-cache/lookup.js
Module not found: Error: Can't resolve 'dgram' in 'E:\xampp\htdocs\khaleesi\node_modules\native-dns-cache'
@ ./node_modules/native-dns-cache/lookup.js 21:12-28
@ ./node_modules/native-dns-cache/index.js
@ ./node_modules/native-dns/lib/platform.js
@ ./node_modules/native-dns/dns.js
@ ./node_modules/dns/lib/dns.js
@ ./node_modules/mikronode/dist/mikronode.js
@ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/Mikronode.vue
@ ./src/components/Mikronode.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/native-dns/lib/server.js
Module not found: Error: Can't resolve 'dgram' in 'E:\xampp\htdocs\khaleesi\node_modules\native-dns\lib'
@ ./node_modules/native-dns/lib/server.js 23:12-28
@ ./node_modules/native-dns/dns.js
@ ./node_modules/dns/lib/dns.js
@ ./node_modules/mikronode/dist/mikronode.js
@ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/Mikronode.vue
@ ./src/components/Mikronode.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/native-dns/lib/utils.js
Module not found: Error: Can't resolve 'dgram' in 'E:\xampp\htdocs\khaleesi\node_modules\native-dns\lib'
@ ./node_modules/native-dns/lib/utils.js 21:12-28
@ ./node_modules/native-dns/lib/platform.js
@ ./node_modules/native-dns/dns.js
@ ./node_modules/dns/lib/dns.js
@ ./node_modules/mikronode/dist/mikronode.js
@ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/Mikronode.vue
@ ./src/components/Mikronode.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/native-dns/lib/platform.js
Module not found: Error: Can't resolve 'fs' in 'E:\xampp\htdocs\khaleesi\node_modules\native-dns\lib'
@ ./node_modules/native-dns/lib/platform.js 23:9-22
@ ./node_modules/native-dns/dns.js
@ ./node_modules/dns/lib/dns.js
@ ./node_modules/mikronode/dist/mikronode.js
@ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/Mikronode.vue
@ ./src/components/Mikronode.vue
@ ./src/router/index.js
@ ./src/main.js

Build failed with errors.

Confused by versions numbering...

master and npm show version 0.3.3 but it hasn't been touched in 5 years.
release shows version 0.3.1 and is more recent.

Which is the official version?

'/interface/ethernet/getall' on timer is crashing

I'm running chan.write("/interface/ethernet/getall"); in after few seconds I receive this error:

D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:2318 throw err; ^ SyntaxError: Expected "!done", "!fatal", "!re", "!trap", ".tag=", [ \t\r\n\x0C\0x00], or [\0x00] but "=" found. at peg$buildStructuredError (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:21384:15) at Object.peg$parse [as parse] (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:22244:14) at MapSubscriber.project (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:474:39) at MapSubscriber._next (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:13275:36) at MapSubscriber.Subscriber.next (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:2213:19) at DoSubscriber._next (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:11099:31) at DoSubscriber.Subscriber.next (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:2213:19) at MapSubscriber._next (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:13281:27) at MapSubscriber.Subscriber.next (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:2213:19) at Subject.next (D:\Undefined Project\watcher\node_modules\mikronode\dist\mikronode.js:1805:26)

What problem after connection when i running from another file?

What problem after connection?

var umk = require("./umk.js");
var umkr = require("./umkr.js");
var xid = '';

umkr.rbFppp('00:AA:22:36:DA:12','10.0.155.20','mkap','aa10aa',function removeid(s){
var js1 = JSON.stringify(s);
console.log('StringiFy: '+js1);
var obj = JSON.parse(js1);
xid = obj[0]['.id'];
umk.rbRppp(xid, function res(s){
console.log('Retorno: '+s);
});
});

========= umkr.js =============
// get .id of a ppp user from caller-id

var rbFppp = function(clid, vhostorip, vuser, vpass, callback){
var api = require('mikronode');
var connection = new api(vhostorip,vuser,vpass);
connection.connect(function(conn) { // after this line aplication return nothing
var chan=conn.openChannel();
chan.write(
['/ppp/active/print','?caller-id='+clid,'=.proplist=.id,caller-id,name,address,uptime']
,function() {
chan.on('done',function(data) {
var parsed = api.parseItems(data);
callback(parsed);
chan.close();
conn.close();
});
});
});
};

module.exports.rbFppp = rbFppp;

========== umk.js ============
// remove ppp user
var rbRppp = function(vid,cb){
var api = require('mikronode');
var connection = new api('10.0.155.20','mkap','aa10aa');
connection.connect(function(conn) {
var chan=conn.openChannel();
chan.write(['/ppp/active/remove','=.id='+vid],function() {
chan.on('trap',function(data) {
cb('Error setting IP: '+JSON.stringify(data));
});
chan.on('done',function(data) {
cb('Ok.');
});
chan.close();
conn.close();
});
});

};

module.exports.rbRppp = rbRppp;

"find" issue

how can i use "find" in "/ppp/secret/disable" ?

Expected "=", [ \t\r\n\x0C\0x00], or [a-zA-Z_\-0-9] but end of input found.

I want to send SMS by the Mikrotik router, here is my code:

channel.write('/tool/sms/send', {
   'phone-number': '00420123456789',
   'message': 'Test',
   'port': 'usb1'
});

SMS has been sent (and received), but i get this error message from mikronode:

***************************************************************************
***************************************************************************
Error processing sentence: { SyntaxError: Expected "=", [ \t\r\n\x0C\0x00], or [a-zA-Z_\-0-9] but end of input found.
    at peg$buildStructuredError (D:\test\node_modules\mikronode\dist\mikronode.js:21362:15)
    at Object.peg$parse [as parse] (D:\test\node_modules\mikronode\dist\mikronode.js:22222:14)
    at MapSubscriber.project (D:\test\node_modules\mikronode\dist\mikronode.js:479:39)
    at MapSubscriber._next (D:\test\node_modules\mikronode\dist\mikronode.js:13247:36)
    at MapSubscriber.Subscriber.next (D:\test\node_modules\mikronode\dist\mikronode.js:2185:19)
    at MapSubscriber._next (D:\test\node_modules\mikronode\dist\mikronode.js:13253:27)
    at MapSubscriber.Subscriber.next (D:\test\node_modules\mikronode\dist\mikronode.js:2185:19)
    at DoSubscriber._next (D:\test\node_modules\mikronode\dist\mikronode.js:11071:31)
    at DoSubscriber.Subscriber.next (D:\test\node_modules\mikronode\dist\mikronode.js:2185:19)
    at Subject.next (D:\test\node_modules\mikronode\dist\mikronode.js:1777:26)
    at ScanSubscriber.accumulator (D:\test\node_modules\mikronode\dist\mikronode.js:522:41)
    at ScanSubscriber._tryNext (D:\test\node_modules\mikronode\dist\mikronode.js:15114:28)
    at ScanSubscriber._next (D:\test\node_modules\mikronode\dist\mikronode.js:15107:26)
    at ScanSubscriber.Subscriber.next (D:\test\node_modules\mikronode\dist\mikronode.js:2185:19)
    at Socket.handler (D:\test\node_modules\mikronode\dist\mikronode.js:5272:47)
    at emitOne (events.js:115:13)
    at Socket.emit (events.js:210:7)
    at addChunk (_stream_readable.js:252:12)
    at readableAddChunk (_stream_readable.js:239:11)
    at Socket.Readable.push (_stream_readable.js:197:10)
    at TCP.onread (net.js:589:20)
  message: 'Expected "=", [ \\t\\r\\n\\x0C\\0x00], or [a-zA-Z_\\-0-9] but end of input found.',
  expected: 
   [ { type: 'class',
       parts: [Array],
       inverted: false,
       ignoreCase: false },
     { type: 'class',
       parts: [Array],
       inverted: false,
       ignoreCase: false },
     { type: 'literal', text: '=', ignoreCase: false } ],
  found: null,
  location: 
   { start: { offset: 24, line: 2, column: 21 },
     end: { offset: 24, line: 2, column: 21 } },
  name: 'SyntaxError' }
Skipping and continuing
***************************************************************************
***************************************************************************

Here is log from router:

16:55:25 gsm,write,debug \1B\r 
16:55:25 gsm,write,debug 
16:55:25 gsm,write,debug AT\r 
16:55:25 gsm,write,debug 
16:55:25 gsm,read,debug AT 
16:55:25 gsm,read,debug OK 
16:55:25 gsm,write,debug AT+CPIN?\r 
16:55:25 gsm,write,debug 
16:55:25 gsm,read,debug AT+CPIN? 
16:55:25 gsm,read,debug +CPIN: READY 
16:55:25 gsm,read,debug OK 
16:55:25 gsm,write,debug AT+CMGF=0\r 
16:55:25 gsm,write,debug 
16:55:25 gsm,read,debug AT+CMGF=0 
16:55:25 gsm,read,debug OK 
16:55:25 gsm,write,debug AT+CMGS=18\r 
16:55:25 gsm,read,debug AT+CMGS=18 
16:55:25 gsm,read,debug >  
16:55:25 gsm,write,debug 0021000E8100247047244692001104D4F29C0E\1A 

Could you help me, please?

Node.js 6.1.0+ not working

Login failure returned from Mikrotik API on Node.js except LTS versions.
Probably because of some connect/hashing node api changes.

Hotfix: use Node.js in LTS version (eg. 4.4.4)

Unable to set or update queue

I'm trying to update a queue max-limit but I'm not sure which is the correct format for it, I tried:

  1. chann.write(['/queue/simple/set', `?name=121`, `=max-limit=10k/10k`])
  2. chann.write(['/queue/simple/set', `name=121`, `=max-limit=10k/10k`])
  3. chann.write(['/queue/simple/set', `121`, `=max-limit=10k/10k`])

None of these formats allow me to update the rule properly, any guidance about how to do it will be well received

example typo/error

Hey, :)

Thanks for the lib.

Small typo in the example, left out the 2 :)

    chan2.write('/ip/firewall/print');

    chan2.done.subscribe(function(data){

         // data is all of the sentences in an array.
         data.forEach(function(item) {
            var data = MikroNode.resultsToObj(item.data); // convert array of field items to object.
            console.log('Interface/IP: '+data.interface+"/"+data.address);
         });

    });

});

Can't get Mikronode to work with /queue simple

I'm trying the following using mikronode:

var api = require('mikronode');

var connection = new api('192.168.0.5','admin', 'password');
connection.connect(function(conn) {
    var chan=conn.openChannel();

    chan.write(['/queue/simple/set', '=numbers=1', '=limit-at=256K/512K', '=max-limit=256K/512K', '=burst-limit=256K/512K', '=burst-time=10/10'],function() {
        chan.on('done',function(data) {
            var parsed = api.parseItems(data);
            console.log("response", parsed)
            chan.close();
            conn.close();

        });
    });
});

Nothing happens. Queue1 is unaffected and no out put is returned.
I've verified that mikronode is connecting to the router . The following works as expected in the console:
/queue simple set numbers=1 max-limit=1024K/2048K limit-at=1024K/2048K burst-limit=1024K/2048K burst-time=10/10

problem with executing channel sync() function

var MikroNode = require('mikronode');

var device = new MikroNode('192.168.43.182');
device.setDebug(MikroNode.DEBUG);
device.connect('admin', 'admin').then(function (conn) {
    conn.closeOnDone(true); 
    let chan = conn.openChannel('1')
    //chan.sync(true);
    chan.sync(true)
    chan.write('/tool/user/user/add',{
        'customer':'admin',
        'username':'user',
        'password':'user'
    })
    chan.write('/tool/user/user/print')
});

will not complete it gets stuck creating channel 1

but without it it works

var MikroNode = require('mikronode');

var device = new MikroNode('192.168.43.182');
device.setDebug(MikroNode.DEBUG);
device.connect('admin', 'admin').then(function (conn) {
    conn.closeOnDone(true); 
    let chan = conn.openChannel('1')
    //chan.sync(true)
    chan.write('/tool/user/user/add',{
        'customer':'admin',
        'username':'user',
        'password':'user'
    })
    chan.write('/tool/user/user/print')
});

.connect crashes on attempted connection if api is turned off in radio

If the API is turned off in the mikrotik radio, the attempt to connect causes an error which completely crashes the node process. It won't trap it, and I also cannot catch it.

I know the code that Im using is fine, as if I use it on a radio that the api is turned on in I have no issues at all.

It returns
events.js:72
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED
at errnoException (net.js:901:11)
at Object.afterConnect as oncomplete

With the code:
mtik_connection = new mtik(bwtest_ip, mtik_user, mtik_pass, {debug : 5});
mtik_connection.closeOnDone(true);
mtik_connection.connect(function(conn) {}) //<- this line

In theory, the right way to fix this is to use the api to talk to the radio to turn it on, but its the api thats turned off and is refusing all access.

Is there a way to check if the api is turned on in the radio that wont crash the node process, or return 'could not connect due to api' without dieing?

Close on done doesn't actually close connection on done.

In the es2015 bracnh, when both streams are complete, the socket should disconnect.

api.connect('test','').then(
    function(c) { 
        conn=c;
        console.log("Connected");
        var channel1=conn.openChannel();
        conn.closeOnDone(true);
        var channel2=conn.openChannel();
        channel1.write('/ip/address/print');
        channel2.write('/user/active/listen');

        channel1.data.subscribe(e=>console.log("Data 1: ",e));
        channel2.data.subscribe(e=>console.log("Data 2: ",e));

        setTimeout(function(){channel2.write('/cancel')},3000);
    }
  , function(err) {
        console.log("Error occured while connecting ",err);
    }
);

Not compatible with newer versions of node (^2.0.0-beta.7)

LTS is currently at v6.10.1

var connection = MikroNode.getConnection('93.190.116.3','admin','L1bertyad');

TypeError: MikroNode.getConnection is not a function
at Object. (C:\Users\AMeusel\Dropbox\GitHub\liberty-tree\tree.js:67:28)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:393:7)
at startup (bootstrap_node.js:150:9)
at bootstrap_node.js:508:3

file npm-debug.log
0 info it worked if it ends with ok
1 verbose cli [ 'C:\Program Files\nodejs\node.exe',
1 verbose cli 'C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js',
1 verbose cli 'install',
1 verbose cli 'mikronode' ]
2 info using [email protected]
3 info using [email protected]
4 silly loadCurrentTree Starting
5 silly install loadCurrentTree
6 silly install readLocalPackageData
7 silly fetchPackageMetaData mikronode@^1.0.3
8 silly fetchNamedPackageData mikronode
9 silly mapToRegistry name mikronode
10 silly mapToRegistry using default registry
11 silly mapToRegistry registry https://registry.npmjs.org/
12 silly mapToRegistry data Result {
12 silly mapToRegistry raw: 'mikronode',
12 silly mapToRegistry scope: null,
12 silly mapToRegistry escapedName: 'mikronode',
12 silly mapToRegistry name: 'mikronode',
12 silly mapToRegistry rawSpec: '',
12 silly mapToRegistry spec: 'latest',
12 silly mapToRegistry type: 'tag' }
13 silly mapToRegistry uri https://registry.npmjs.org/mikronode
14 verbose request uri https://registry.npmjs.org/mikronode
15 verbose request no auth needed
16 info attempt registry request try #1 at 3:38:31 PM
17 verbose request id c70da22766bd6596
18 verbose etag "592834Z25VS5IIKMOMNO8I9Q3"
19 http request GET https://registry.npmjs.org/mikronode
20 http 200 https://registry.npmjs.org/mikronode
21 verbose headers { server: 'nginx/1.10.1',
21 verbose headers 'content-type': 'application/json',
21 verbose headers 'last-modified': 'Thu, 15 Dec 2016 01:40:38 GMT',
21 verbose headers etag: 'W/"5851f496-755c"',
21 verbose headers 'content-encoding': 'gzip',
21 verbose headers 'cache-control': 'max-age=300',
21 verbose headers 'content-length': '6153',
21 verbose headers 'accept-ranges': 'bytes',
21 verbose headers date: 'Mon, 03 Apr 2017 14:38:32 GMT',
21 verbose headers via: '1.1 varnish',
21 verbose headers age: '0',
21 verbose headers connection: 'keep-alive',
21 verbose headers 'x-served-by': 'cache-lcy1124-LCY',
21 verbose headers 'x-cache': 'MISS',
21 verbose headers 'x-cache-hits': '0',
21 verbose headers 'x-timer': 'S1491230312.207835,VS0,VE36',
21 verbose headers vary: 'Accept-Encoding' }
22 silly get cb [ 200,
22 silly get { server: 'nginx/1.10.1',
22 silly get 'content-type': 'application/json',
22 silly get 'last-modified': 'Thu, 15 Dec 2016 01:40:38 GMT',
22 silly get etag: 'W/"5851f496-755c"',
22 silly get 'content-encoding': 'gzip',
22 silly get 'cache-control': 'max-age=300',
22 silly get 'content-length': '6153',
22 silly get 'accept-ranges': 'bytes',
22 silly get date: 'Mon, 03 Apr 2017 14:38:32 GMT',
22 silly get via: '1.1 varnish',
22 silly get age: '0',
22 silly get connection: 'keep-alive',
22 silly get 'x-served-by': 'cache-lcy1124-LCY',
22 silly get 'x-cache': 'MISS',
22 silly get 'x-cache-hits': '0',
22 silly get 'x-timer': 'S1491230312.207835,VS0,VE36',
22 silly get vary: 'Accept-Encoding' } ]
23 verbose get saving mikronode to C:\Users\AMeusel\AppData\Roaming\npm-cache\registry.npmjs.org\mikronode.cache.json
24 verbose correctMkdir C:\Users\AMeusel\AppData\Roaming\npm-cache correctMkdir not in flight; initializing
25 silly fetchPackageMetaData Error: No compatible version found: mikronode@^1.0.3
25 silly fetchPackageMetaData Valid install targets:
25 silly fetchPackageMetaData 2.0.0, 2.0.0-beta.7, 2.0.0-beta.6, 2.0.0-beta.5, 2.0.0-beta.4, 2.0.0-beta.2, 0.3.3, 0.3.2, 0.3.1, 0.3.0, 0.2.1, 0.2.0, 0.1.0
25 silly fetchPackageMetaData
25 silly fetchPackageMetaData at pickVersionFromRegistryDocument (C:\Program Files\nodejs\node_modules\npm\lib\fetch-package-metadata.js:178:16)
25 silly fetchPackageMetaData at C:\Program Files\nodejs\node_modules\npm\node_modules\iferr\index.js:13:50
25 silly fetchPackageMetaData at C:\Program Files\nodejs\node_modules\npm\lib\utils\pulse-till-done.js:20:8
25 silly fetchPackageMetaData at saved (C:\Program Files\nodejs\node_modules\npm\lib\cache\caching-client.js:174:7)
25 silly fetchPackageMetaData at C:\Program Files\nodejs\node_modules\npm\node_modules\graceful-fs\polyfills.js:241:18
25 silly fetchPackageMetaData at FSReqWrap.oncomplete (fs.js:123:15)
25 silly fetchPackageMetaData error for mikronode@^1.0.3 { Error: No compatible version found: mikronode@^1.0.3
25 silly fetchPackageMetaData Valid install targets:
25 silly fetchPackageMetaData 2.0.0, 2.0.0-beta.7, 2.0.0-beta.6, 2.0.0-beta.5, 2.0.0-beta.4, 2.0.0-beta.2, 0.3.3, 0.3.2, 0.3.1, 0.3.0, 0.2.1, 0.2.0, 0.1.0
25 silly fetchPackageMetaData
25 silly fetchPackageMetaData at pickVersionFromRegistryDocument (C:\Program Files\nodejs\node_modules\npm\lib\fetch-package-metadata.js:178:16)
25 silly fetchPackageMetaData at C:\Program Files\nodejs\node_modules\npm\node_modules\iferr\index.js:13:50
25 silly fetchPackageMetaData at C:\Program Files\nodejs\node_modules\npm\lib\utils\pulse-till-done.js:20:8
25 silly fetchPackageMetaData at saved (C:\Program Files\nodejs\node_modules\npm\lib\cache\caching-client.js:174:7)
25 silly fetchPackageMetaData at C:\Program Files\nodejs\node_modules\npm\node_modules\graceful-fs\polyfills.js:241:18
25 silly fetchPackageMetaData at FSReqWrap.oncomplete (fs.js:123:15) code: 'ETARGET' }
26 silly rollbackFailedOptional Starting
27 silly rollbackFailedOptional Finishing
28 silly runTopLevelLifecycles Finishing
29 silly install printInstalled
30 verbose stack Error: No compatible version found: mikronode@^1.0.3
30 verbose stack Valid install targets:
30 verbose stack 2.0.0, 2.0.0-beta.7, 2.0.0-beta.6, 2.0.0-beta.5, 2.0.0-beta.4, 2.0.0-beta.2, 0.3.3, 0.3.2, 0.3.1, 0.3.0, 0.2.1, 0.2.0, 0.1.0
30 verbose stack
30 verbose stack at pickVersionFromRegistryDocument (C:\Program Files\nodejs\node_modules\npm\lib\fetch-package-metadata.js:178:16)
30 verbose stack at C:\Program Files\nodejs\node_modules\npm\node_modules\iferr\index.js:13:50
30 verbose stack at C:\Program Files\nodejs\node_modules\npm\lib\utils\pulse-till-done.js:20:8
30 verbose stack at saved (C:\Program Files\nodejs\node_modules\npm\lib\cache\caching-client.js:174:7)
30 verbose stack at C:\Program Files\nodejs\node_modules\npm\node_modules\graceful-fs\polyfills.js:241:18
30 verbose stack at FSReqWrap.oncomplete (fs.js:123:15)
31 verbose cwd C:\Users\AMeusel\Dropbox\GitHub\liberty-tree
32 error Windows_NT 10.0.14393
33 error argv "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "install" "mikronode"
34 error node v6.10.1
35 error npm v3.10.10
36 error code ETARGET
37 error notarget No compatible version found: mikronode@^1.0.3
37 error notarget Valid install targets:
37 error notarget 2.0.0, 2.0.0-beta.7, 2.0.0-beta.6, 2.0.0-beta.5, 2.0.0-beta.4, 2.0.0-beta.2, 0.3.3, 0.3.2, 0.3.1, 0.3.0, 0.2.1, 0.2.0, 0.1.0
38 error notarget This is most likely not a problem with npm itself.
38 error notarget In most cases you or one of your dependencies are requesting
38 error notarget a package version that doesn't exist.
39 verbose exit [ 1, true ]

/ip/dns/static/set

I am struggling to update the address of an existing static DNS entry:

chan.write(['/ip/dns/static/set','=address=' + dhcp[i].address,'=.id=' + dhcp[i]['.id']],function() {
    chan.on('trap',function(data) {
        console.log(util.inspect(data, false,2,true));
    });
});

Where dhcp[i]['.id'] has been retrieved previously

{ '.id': '*3B',
  address: '10.0.1.253',
  'mac-address': '4C:5E:0C:72:4A:C1',
  'client-id': '1:4c:5e:c:72:4a:c1',
  'address-lists': '',
  server: 'WottonHouse',
  'dhcp-option': '',
  status: 'bound',
  'expires-after': '5m12s',
  'last-seen': '4m48s',
  'active-address': '10.0.1.253',
  'active-mac-address': '4C:5E:0C:72:4A:C1',
  'active-client-id': '1:4c:5e:c:72:4a:c1',
  'active-server': 'WottonHouse',
  'host-name': 'WOT-AP001',
  'src-mac-address': '02:91:CC:B3:A1:22',
  radius: 'false',
  dynamic: 'true',
  blocked: 'false',
  disabled: 'false' }

the trap is triggered and no change occurs on the gateway so its clear there is an error (which i don't mind), however the data variable returned is always empty, which has left me a bit 😕, with no idea where to proceed

Complete code and output below

var api = require('mikronode');
var util = require('util');
var connection = new api('XXX.XXX.XXX.XXX','XXX','XXX');
var dns = [];
var dhcp = [];
var regex = /^[A-Z]{3}-(AP|SW)\d{3}$/i
function sortDNS(a,b) {
  if (a['.id'] < b['.id'])
     return -1;
  if (a['.id'] > b['.id'])
    return 1;
  return 0;
}
function sortDHCP(a,b) {
  if (a['host-name'] < b['host-name'])
     return -1;
  if (a['host-name'] > b['host-name'])
    return 1;
  return 0;
}
connection.connect(function(conn) {
    var chan=conn.openChannel();
    chan.write('/ip/dns/static/print',function() {
        chan.on('done',function(data) {
            var parsed = api.parseItems(data);
            parsed.forEach(function(item) {
                dns.push(item);
            });
            chan.write('/ip/dhcp-server/lease/print',function() {
                chan.on('done',function(data) {
                    var parsed = api.parseItems(data);
                    parsed.forEach(function(item) {
                        item['host-name'] = String(item['host-name']).replace(/\u0000/,'');
                        if ((item['host-name'].match(regex)) && (item.status == 'bound')) {
                            dhcp.push(item);
                        }
                    });
                    dns.sort(sortDNS);
                    dhcp.sort(sortDHCP);
                    for (i = 0; i < dns.length; i++) { 
                        exists = false;
                        for (j = 0; j < dhcp.length; j++) {
                            if (dhcp[j]['host-name'] == dns[i].name) {
                                exists = true
                            }
                        }
                        if (!exists) {
                            //exists in the DNS but not the DHCP //remove from DNS
                        }
                    }
                    for (i = 0; i < dhcp.length; i++) { 
                        exists = false;
                        for (j = 0; j < dns.length; j++) {
                            if (dns[j].name == dhcp[i]['host-name']) {
                                if (dns[j].address != dhcp[i].address) {
                                    chan.write(['/ip/dns/static/set','=address=' + dhcp[i].address,'=.id=' + dhcp[i]['.id']],function() {
                                        chan.on('trap',function(data) {
                                            console.log(util.inspect(data, false,2,true));
                                        });
                                    });
                                }
                                exists = true
                            }
                        }
                        if (!exists) {
                            chan.write(['/ip/dns/static/add','=name=' + dhcp[i]['host-name'],'=address=' + dhcp[i].address,'=ttl=00:05:00'],function() {
                                chan.on('trap',function(data) {
                                    console.error('Error creating DNS entry');
                                });
                            });
                        }
                    }
                });
            });
        });
    });
});
9 Feb 21:09:05 - [32m[nodemon] starting `node server.js`[39m
{ '.id': '*412',
  name: 'WOT-AP001',
  address: '10.0.1.1',
  ttl: '5m',
  dynamic: 'false',
  regexp: 'false',
  disabled: 'false' }
{ '.id': '*3B',
  address: '10.0.1.253',
  'mac-address': '4C:5E:0C:72:4A:C1',
  'client-id': '1:4c:5e:c:72:4a:c1',
  'address-lists': '',
  server: 'WottonHouse',
  'dhcp-option': '',
  status: 'bound',
  'expires-after': '8m7s',
  'last-seen': '1m53s',
  'active-address': '10.0.1.253',
  'active-mac-address': '4C:5E:0C:72:4A:C1',
  'active-client-id': '1:4c:5e:c:72:4a:c1',
  'active-server': 'WottonHouse',
  'host-name': 'WOT-AP001',
  'src-mac-address': '02:91:CC:B3:A1:22',
  radius: 'false',
  dynamic: 'true',
  blocked: 'false',
  disabled: 'false' }
{}

Getting unexpected clean exit on login :(

Hello! I'm getting really strange behavior with mikronode login method.

On some devices I connect It does clean exit (I assume process.exit(0) somewhere in package) on connect() method.

Here is code I use

async function mtkApiValidate(host, user, pass) {
  let Device = new mikroNode(host, 8728, 3);
  let result = false;
  await Device.connect(user, pass)
  .then(([login]) => login(user, pass))
    .then(async function (conn) {
      result = true;
      await conn.close()
    })
    .catch(async function (err) {
      let msg;
      if (typeof (err) == 'string') {
        msg = err;
      } else {
        msg = JSON.stringify(err)
      }
      logger.error(`Unable to connect to ${host} => ${user}:${pass}, error was : ${msg}`);
    })
  return result;

Try this IP 94.230.155.137 with any login/pass. It wont get pass login() line, doesnt go into catch. Just clean exit???

Please help.

mikronode needs rxjs 5.3.0

Would be need to add an advertising that install can fail because the last version of rxjs (6.4.0) not work with mikronode.
If install rxjs by default, it is installed the last version, and when mikronode attemp to connect with routerOS, throws this error:

Unhandled rejection:  {}
Rejected {
context: { parent: { parent: undefined } },
id: 1,
value:
TypeError: _sentence$.get(...).do is not a function

Seems as rxjs it is not installed, but is no the case:

npm list mikronode
├── [email protected] 
└── UNMET PEER DEPENDENCY [email protected]

rxjs is installed, but claim for unmet dependency. If I try to install:

npm install rxjs
npm WARN [email protected] requires a peer of rxjs@^5.3.0 but none is installed. You must install peer dependencies yourself.

The solution is install rxjs 5.3.0 manually:

npm install rxjs@^5.3.0

Seems to be a silly problem, but it took me too long to realize it. Perhaps someone else finds the warning useful.

parameter '= count-only =' does not return response

Seems to be same problem as described in #12.
When I make an API request through mikronode with ["/ip/address/print", "=count-only="] as parameter to chat.write it does no returns any value.

API request with just "/ip/address/print" returns proper results. I have tested with ipCountOnly.js example in node v6.10.3.

query word has broken.

Yo Man

I'm upgrading my library from version 2.0.1 to the latest 2.3.x. Found an issue with the query word I use with the print command.

channel.write('/ip/dhcp-server/lease/print', { address: '10.0.0.25' }

should have in the socket level translate the argument object into

?=address=10.200.0.250

but it's getting me

?address=10.200.0.250

which is not going to work.

Mixed answers between channels

Good day.
I'm using mikronode mainly for mikrotik router port manipulation.
During initial state I disable needed ports in loop with promises using one persistent connection to Mikrotik and one-per-command channel. I tested "bad port" port situation and noticed that sometimes i get "no such item" error on working, configured ports that usually work OK. And that happened right after real "bad" port.
Normal situation:

[19.06 08:46:08] ER: 0:ether28 port down failed!!! Reason: no such item
[19.06 08:46:08] OK: 0:ether14 port down
[19.06 08:46:08] OK: 0:ether13 port down
[19.06 08:46:08] OK: 0:ether12 port down
[19.06 08:46:08] OK: 0:ether11 port down
[19.06 08:46:08] OK: 0:ether10 port down
[19.06 08:46:08] OK: 0:ether9 port down
[19.06 08:46:08] OK: 0:ether8 port down
[19.06 08:46:08] OK: 0:ether7 port down
[19.06 08:46:08] OK: 0:ether6 port down
[19.06 08:46:08] OK: 0:ether5 port down

Bad answers:

[19.06 08:46:17] ER: 0:ether28 port down failed!!! Reason: no such item
[19.06 08:46:17] ER: 0:ether14 port down failed!!! Reason: no such item
[19.06 08:46:17] ER: 0:ether13 port down failed!!! Reason: no such item
[19.06 08:46:17] ER: 0:ether12 port down failed!!! Reason: no such item
[19.06 08:46:17] OK: 0:ether11 port down
[19.06 08:46:17] OK: 0:ether10 port down
[19.06 08:46:17] OK: 0:ether9 port down
[19.06 08:46:17] OK: 0:ether8 port down
[19.06 08:46:17] OK: 0:ether7 port down
[19.06 08:46:17] OK: 0:ether6 port down
[19.06 08:46:17] OK: 0:ether5 port down

After turning on debugging I saw (if I understand it right) real problem - the answer is received in the same channel and what is more strange - seems that channels are not created right.

Creating channel  1529398091373
Channel 1529398091373 Created
Writing on channel 1529398091373 /interface/ethernet/disable { numbers: 'ether28' }
Creating channel  1529398091373
Channel 1529398091373 Created
Writing on channel 1529398091373 /interface/ethernet/disable { numbers: 'ether14' }
Creating channel  1529398091389
Channel 1529398091389 Created
Writing on channel 1529398091389 /interface/ethernet/disable { numbers: 'ether13' }
Creating channel  1529398091389
Channel 1529398091389 Created
Writing on channel 1529398091389 /interface/ethernet/disable { numbers: 'ether12' }
Creating channel  1529398091389
Channel 1529398091389 Created
Writing on channel 1529398091389 /interface/ethernet/disable { numbers: 'ether11' }
Creating channel  1529398091389
Channel 1529398091389 Created
Writing on channel 1529398091389 /interface/ethernet/disable { numbers: 'ether10' }
Creating channel  1529398091389
Channel 1529398091389 Created
Writing on channel 1529398091389 /interface/ethernet/disable { numbers: 'ether9' }
Creating channel  1529398091404
Channel 1529398091404 Created
Writing on channel 1529398091404 /interface/ethernet/disable { numbers: 'ether8' }
Creating channel  1529398091404
Channel 1529398091404 Created
Writing on channel 1529398091404 /interface/ethernet/disable { numbers: 'ether7' }
Creating channel  1529398091404
Channel 1529398091404 Created
Writing on channel 1529398091404 /interface/ethernet/disable { numbers: 'ether6' }
Creating channel  1529398091404
Channel 1529398091404 Created
Writing on channel 1529398091404 /interface/ethernet/disable { numbers: 'ether5' }
Creating channel  1529398091404
Channel 1529398091404 Created
Writing on channel 1529398091404 /interface/ethernet/disable { numbers: 'ether5' }
Login stream complete
Channel (1529398091373)::TRAP
*** Register Command: trap 1 { type: 'trap',
  tag: '1529398091373',
  data: [ { field: 'message', value: 'no such item' } ],
  cmd:
   { id: 1,
     command: '/interface/ethernet/disable',
     args: { numbers: 'ether28' } } }
[19.06 08:48:11] ------------------------------------------ER: 0:ether28 port down failed!!! Reason: no such item
Channel (1529398091373)::CLOSED
Closing channel  1529398091373
Channel (1529398091373)::TRAP
*** Register Command: trap 1 { type: 'trap',
  tag: '1529398091373',
  data: [ { field: 'message', value: 'no such item' } ],
  cmd:
   { id: 1,
     command: '/interface/ethernet/disable',
     args: { numbers: 'ether14' } } }
[19.06 08:48:11] ------------------------------------------ER: 0:ether14 port down failed!!! Reason: no such item
Channel (1529398091373)::CLOSED
Closing channel  1529398091373
Channel (1529398091389)::data flatMap
Channel (1529398091389)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether13 port down
Channel (1529398091389)::CLOSED
Closing channel  1529398091389
Channel (1529398091389)::data flatMap
Channel (1529398091389)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether12 port down
Channel (1529398091389)::CLOSED
Closing channel  1529398091389
Channel (1529398091389)::data flatMap
Channel (1529398091389)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether11 port down
Channel (1529398091389)::CLOSED
Closing channel  1529398091389
Channel (1529398091389)::data flatMap
Channel (1529398091389)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether10 port down
Channel (1529398091389)::CLOSED
Closing channel  1529398091389
Channel (1529398091389)::data flatMap
Channel (1529398091389)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether9 port down
Channel (1529398091389)::CLOSED
Closing channel  1529398091389
Channel (1529398091404)::data flatMap
Channel (1529398091404)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether8 port down
Channel (1529398091404)::CLOSED
Closing channel  1529398091404
Channel (1529398091404)::data flatMap
Channel (1529398091404)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether7 port down
Channel (1529398091404)::CLOSED
Closing channel  1529398091404
Channel (1529398091404)::data flatMap
Channel (1529398091404)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether6 port down
Channel (1529398091404)::CLOSED
Closing channel  1529398091404
Channel (1529398091404)::data flatMap
Channel (1529398091404)::done_ret flatMap
[19.06 08:48:11] OK: 0:ether5 port down
Channel (1529398091404)::CLOSED
Closing channel  1529398091404
Login stream complete
Channel (1529398091404)::data flatMap
Channel (1529398091404)::done_ret flatMap
[19.06 08:48:11] OK: 1:ether5 port down
Channel (1529398091404)::CLOSED
Closing channel  1529398091404
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1
Clearing command cache for # 1

There's one incorrect answer right after the real "bad" port operation.
There can be upto 6 answers in the same channel.

Another bad thing is that in last log 2 ports "ether5" are downed on different connections to different routers but work on the same channel.

I may be wrong in my conclusions but please explain me what i'm doing wrong if I do.

Node: v.8.9.1
Mikronode: v.2.3.11
RouterOS: v.6.40.3

RouterOS 6.43rc45 changes the login authorisation process

Just a heads up:

Login method pre-v6.43:
/login
!done
=ret=ebddd18303a54111e2dea05a92ab46b4
/login
=name=admin
=response=001ea726ed53ae38520c8334f82d44c9f2
!done

First, clients sends /login command.
Reply contains =ret=challenge argument.
Client sends second /login command, with =name=username and =response=response.
In case of error, reply contains =ret=error message.
In case of successful login client can start to issue commands.

Login method post-v6.43:

/login
=name=admin
=password=
!done

Now client sends username and password in first message.
Password is sent in plain text.
in case of error, reply contains =message=error message.
In case of successful login client can start to issue commands.

 

How to catch errors on device.connect?

It seems that I can not find how to capture the errors on device.connect(), for example, in case the host is not available.

This is what I tried, nothing works:

function(err)

device.connect().then(([login])=>login('username','password')).then(function(conn) {
    // do stuff
},function(err) {
    console.log("Failed to connect. ",err);  // never reach here
});

device.on('error'...

device.on('error', function(err) {
    console.log("Failed to connect!");  // TypeError: device.on is not a function
});

...and other tests like this:
device.connect().then(([login])=>login('username','password'), function(err){ console.log("Failed to connect!")}).then(function(conn){

The documentation says:
Device.connect([cb]) Connect to the target device. The optional callback function is called after successful connect with the function to call to login as the 2nd parameter, and any connection errors as the first. the connect method returns a Promise that is resolved when connecting.

...but I don't understand how work.

Is any example for that?

api details

Where Can I find a detailed api documentation? for example in winbox I see /ip/hotspot/users/ but if I have to see the list of users I have to use /ip/hotspot/user/print, I dont know what each resource receives, for example I cant see how I can add an user and asign a profile to it. I went to the api section on the mikrotik wiki but I got just a few things from the examples.

[email protected] can't be found after install using npm

This is a follow up on #24

Got same error using beta.5. Please take a look. Thanks.

$ npm install --save mikronode
└─┬ [email protected] 
  └─┬ [email protected] 
    └── [email protected] 

$ ls -b node_modules/
mikronode       rxjs            symbol-observable

$ node
> var api = require('mikronode');
Error: Cannot find module 'mikronode'
    at Function.Module._resolveFilename (module.js:455:15)
    at Function.Module._load (module.js:403:25)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)
    at repl:1:11
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:96:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:313:29)
    at bound (domain.js:280:14)

[email protected] can't be found after install using npm

[email protected] can't be found after install vis npm

$ node -v
v6.6.0

$ npm install mikronode
[email protected] node_modules/mikronode/node_modules/rxjs/node_modules/symbol-observable -> node_modules/symbol-observable
[email protected] node_modules/mikronode/node_modules/rxjs -> node_modules/rxjs
[email protected] /Users/yliu0/git/trepity/router
└── [email protected] 
npm WARN [email protected] No description
npm WARN [email protected] No repository field.

$ ls node_modules/
mikronode       rxjs            symbol-observable

$ node
> var api = require('mikronode');
Error: Cannot find module 'mikronode'
    at Function.Module._resolveFilename (module.js:455:15)
    at Function.Module._load (module.js:403:25)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)
    at repl:1:11
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:96:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:313:29)
    at bound (domain.js:280:14)

cannot find module mikronode

Hello.. first let me thank you for all the hard work made in this project. Im trying to use it now and im getting the error in the screenshot attached
image

I cloned the repository on branch es2015 in the folder node_modules, then i went to that directory and did npm install... then in my script.js i did...
var api=require('mikronode');

and it doesnt work, im doing something wrong? im using node v6.6.0

I tried doing npm install mikronode and the same thing occurs

Thanks in advance!

API-ssl support

Hello,

I am trying to connect to a router on the api-ssl service. It works perfectly on the standard api, but I can't get it to work with SSL, and I can't figure out if it is supported or not.
I use version 2.0.1
In the index.js, on the MikroNode constructor comment there is :

  • @param {(object|boolean)} [options.tls] - Set to true to use TLS for this connection.
  • Set to an object to use TLS and pass the object to tls.connect as the tls
  • options. If your device uses self-signed certificates, you'll either have to
  • set 'rejectUnauthorized : false' or supply the proper CA certificate.

But the method itself has only three parameters (IP, port, timeout), and even if I use the setTLS method to set the options, it seems to me that it is never used.

Also I have tried my router with another client on the api-ssl and managed to connect.

Thanks!

Connection does not close when all channels are complete

When completing all channels and/or connection, the socket should close when the connection is complete.

1: When all connections are complete, the socket should close.
2: A connection should complete if "close on done" is true, and all channels are closed.
3: Channels should close if "close on done" is called, and no commands are in the channel's command queue.
4: Commands cannot be added to a channel or connection's queue if "close on done" is set. This does not count if no commands are currently running on the channel.

Listener action close

How to listen the action close?
I already tried it but it did not work.

  // init

  var device = new MikroNode(host);
  device.connect(login, password).then(function(conn) {
      let chan = conn.openChannel();
      chan.write(['/interface/monitor-traffic', '=interface=<pppoe-pessoa>']);
      chan.data.subscribe(function(data) {
          var packet = MikroNode.resultsToObj(data.data);
          let data_lot = MikroNode.resultsToObj(data.data);
          // test
          chan.close();
      });

      chan.on("close", function() {
          console.log("ok");
      });
  });

Is there any method for listening to close action?

how to use monitor traffic command ?

hi there , I got the problem when i was use command

/interface monitor-traffic interface=ether1 once

when i use this command in mikrotik it response result perfectly because i wants to execute this command only 1 time. here is my code

`

    var api = require('mikronode');
    var device = new api(10.0.0.254'  );
    device.setDebug(api.DEBUG);

    // connect: user, password.
    device.connect().then(([login]) => login('admin', 'admin')).then(function(conn) {
        var c1 = conn.openChannel();
        var c2 = conn.openChannel();
        c1.closeOnDone(true);
        c2.closeOnDone(true);

        console.log('Getting Interfaces');
        c1.write('/interface/monitor-traffic', { 'interface': 'ether1' }); // how to add 'once' to this line ?


        c1.data // get only data here
            .subscribe(function(data) { // feeds in one result line at a time.

                res.json(data)
            })


    }, function(err) {
        console.log("Error connecting:", err);
    });

`

Best regards

Cannot read property 'subscribe' of undefined

While doing the example...

              var chan1=conn.openChannel("interface_listener");
                chan1.write('/interface/listen');
                chan1.read.subscribe(function(item) {
                    var packet=mod.apiMikrotik.resultsToObj(item.data);
                    console.log('Interface change: '+JSON.stringify(packet));
                });

I had this mistake...

erro TypeError: Cannot read property 'subscribe' of undefined
at /var/www/html/sistema/sockets/controllers/mikrotik.js:288:31
at tryCallOne (/var/www/html/sistema/sockets/node_modules/mikronode/dist/mikronode.js:665:13)
at /var/www/html/sistema/sockets/node_modules/mikronode/dist/mikronode.js:751:16
at flush (/var/www/html/sistema/sockets/node_modules/mikronode/dist/mikronode.js:897:30)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickDomainCallback `(internal/process/next_tick.js:128:9)

Can you help me fix it?

conn.connected() actually work?

Seems the conn.connected () return nothing.
Do conn.connected () still work?

var device = new MikroNode('10.0.140.14');
device.connect('user', 'password', {'port': '8291'}).then(function(conn) {
      console.log(conn.connected());  // return nothing
   },function(err) {
      d.resolve("Error connecting API:",err);
   });

Error in doNext unknown parameter

I have following code:

var MikroNode = require('mikronode')
var device = new MikroNode(ipaddress)

device.connect('admin', '').then(connection => {
  console.log('connected')

  var channel = connection.openChannel()
  channel.sync(true)

  console.log('going write 1')

  channel.write('/interface/set', {
    '.id': 'ether2',
    'poe-out': 'forced-on'
  })

  console.log('wrote')

  channel.on('trap', data => {
    console.error(data)
  })

  channel.on('done', data => {
    console.log('done')
    console.log(data)
  })
}).catch(e => {
  throw e
})

And when I launching it, it writes:

connected
going write 1
wrote
Error in doNext unknown parameter

PoE status is not changing. Where I get wrong?
Node version is 7.6.0, mikronode version is 2.1.0

npmjs.com - old version

Hi,

I'm trying to use this but when I installing it from NPM I get 0.3.3 version :)
Do I doing something wrong ?:)

Regards :)

Problem with log in

i don't know what's happen when i try to connect with your example code here is an error.
node version 8.11.3
routeros version 6.40.3

Unhandled rejection: {} Promise { <rejected> TypeError: _sentence$.get(...).do is not a function at new SocketStream (/var/www/zcm/node_modules/mikronode/dist/mikronode.js:474:52) at MikroNode.connect (/var/www/zcm/node_modules/mikronode/dist/mikronode.js:330:30) at _callee5$ (/var/www/zcm/app/controllers/api.controller.js:161:24) at tryCatch (/var/www/zcm/node_modules/babel-polyfill/node_modules/regenerator-runtime/runtime.js:65:40) at Generator.invoke [as _invoke] (/var/www/zcm/node_modules/babel-polyfill/node_modules/regenerator-runtime/runtime.js:303:22) at Generator.prototype.(anonymous function) [as next] (/var/www/zcm/node_modules/babel-polyfill/node_modules/regenerator-runtime/runtime.js:117:21) at step (/var/www/zcm/app/controllers/api.controller.js:31:191) at /var/www/zcm/app/controllers/api.controller.js:31:361 at <anonymous> }

how to nicely handle uncaughtException like the following?

uncaughtException { SyntaxError: Expected "!done", "!fatal", "!re", "!trap", ".tag=", [ \t\r\n\x0C\0x00], or [\0x00] but "=" found

I've got this quite often and I'm at 2.0.1. Wondering why is it happen that often. Any idea? routerOS side of thing? or there is issue inside this library.

Channel error chaining

If error occurs during 1. write(), no other write() can end with success. Both callback/promise approaches are problematic.

Example:

var chan = conn.openChannel();
    chan.write('/ip/address/printXcauseError', function() {
        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);
        });
    });
    chan.write('/ip/address/print', function() {
        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);
        });
    });
    chan.close();

Expected result:
Command failed: no such command()
Interface/IP: ether2-master-local/10.245.235.1/24
Interface/IP: internal-mikrotik/192.168.88.1/24

Obtained result:
Command failed: no such command()
Command failed: no such command()

Listener action close

How to listen the action close?
I already tried it but it did not work.

// init

var device = new MikroNode(host);
device.connect(login, password).then(function(conn) {
let chan = conn.openChannel();
chan.write(['/interface/monitor-traffic', '=interface=']);
chan.data.subscribe(function(data) {
var packet = MikroNode.resultsToObj(data.data);
let data_lot = MikroNode.resultsToObj(data.data);
// test
chan.close();
});

  chan.on("close", function() {
      console.log("ok");
  });

});

Is there any method for listening to close action?

'=count-only=' param

When I execute /ip address print count-only in console it returns a proper value.
But when I make an API request through mikronode with ["/ip/address/print", "=count-only="] as param to chat.write it returns an empty array.

API request with just "/ip/address/print" returns proper results.

Cannot read property 'length' of undefined

Hi Team,

I got following error,

if (d.length<1) return;
^

TypeError: Cannot read property 'length' of undefined
at Socket.loginHandler (D:\examples\mysqlwatch\node_modules\mikronode\lib\index.js:385:26)
at Socket.g (events.js:260:16)
at emitNone (events.js:72:20)
at Socket.emit (events.js:166:7)
at TCPConnectWrap.afterConnect as oncomplete

Error with printing command due to incomplete regex match

I'm trying to print information from a hotspot using /ip/hotspot/print, here is the code:

const device = new MikroNode(ip);
device.connect()
  .then(([login]) => {
    return login(user, pass);
  })
  .then((conn) => {
    conn.closeOnDone(true);
    const chan = conn.openChannel();
    chan.write('/ip/hotspot/print');
    chan.done.subscribe((e) => {
      console.log(e);
      res.send({ data: e });
    });
  });

When I try to test it, it throws a stack trace with the error Expected [.a-z\\-0-9] but "H" found.. Here is the complete stack trace:

Error processing sentence: { SyntaxError: Expected [.a-z\-0-9] but "H" found.
    at peg$buildStructuredError (server/node_modules/mikronode/dist/mikronode.js:2174:13)
    at Object.peg$parse [as parse] (server/node_modules/mikronode/dist/mikronode.js:3201:12)
    at MapSubscriber.project (server/node_modules/mikronode/dist/mikronode.js:486:39)
    at MapSubscriber._next (server/node_modules/rxjs/operators/map.js:79:35)
    at MapSubscriber.Subscriber.next (server/node_modules/rxjs/Subscriber.js:93:18)
    at MapSubscriber._next (server/node_modules/rxjs/operators/map.js:85:26)
    at MapSubscriber.Subscriber.next (server/node_modules/rxjs/Subscriber.js:93:18)
    at DoSubscriber._next (server/node_modules/rxjs/operators/tap.js:88:30)
    at DoSubscriber.Subscriber.next (server/node_modules/rxjs/Subscriber.js:93:18)
    at Subject.next (server/node_modules/rxjs/Subject.js:55:25)
    at ScanSubscriber.accumulator (server/node_modules/mikronode/dist/mikronode.js:529:41)
    at ScanSubscriber._tryNext (server/node_modules/rxjs/operators/scan.js:111:27)
    at ScanSubscriber._next (server/node_modules/rxjs/operators/scan.js:104:25)
    at ScanSubscriber.Subscriber.next (server/node_modules/rxjs/Subscriber.js:93:18)
    at Socket.handler (server/node_modules/rxjs/observable/FromEventObservable.js:210:46)
    at emitOne (events.js:116:13)
  message: 'Expected [.a-z\\-0-9] but "H" found.',
  expected:
   [ { type: 'class',
       parts: [Array],
       inverted: false,
       ignoreCase: false } ],
  found: 'H',
  location:
   { start: { offset: 226, line: 14, column: 2 },
     end: { offset: 227, line: 14, column: 3 } },
  name: 'SyntaxError' }
Skipping and continuing

After a little while of debugging, I figured that the regex that is trying to execute is incomplete, as it doesn't include capital letters, and from the hotspot information, there is a field HTTPS, so the regex fails at that point. The line from the mikronode dist file causing this is at line 1974:

peg$c13 = /^[.a-z\-0-9]/,

After changing it to /^[.a-zA-Z\-0-9]/ it works as expected.

I'd be happy to submit a PR.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.