Wrapping Asynchronous NPM in Meteor - meteor

I am using meteor-npm to use NPM in my Meteor app. I have successfully added serialport and xbee-api. I can read xbee frames using console.log, but I cannot pass the frame to a Meteor method. The code below gives me an error about NPM functions and using bindEnvironment. I'm sure that it has something to do with Meteor running synchronous vs xbee-api running asynchronous. I'm fairly familiar with Meteor, but not with using it with NPM. I believe the answer may be in https://github.com/arunoda/meteor-npm. I don't really need a callback, as I just want the frame data passed to a method and I will handle it from there. Can anyone shed some light on this for me? Thanks in advance.
// Load serialport and xbee-api
var serialport = Meteor.require('serialport');
var SerialPort = serialport.SerialPort;
var xbee_api = Meteor.require('xbee-api');
// Load constants to help with remembering hex codes for xbees
var C = xbee_api.constants;
// Create xbee
var xbee = new xbee_api.XBeeAPI({
api_mode: 2
});
// Create serial port
var serialPort = new SerialPort('/dev/tty.usbserial-A901L66E', {
baudrate: 9600,
// Provided with xbee-api. Could use com.parsers.raw and feed that to xbee-api
parser: xbee.rawParser()
});
// Setup action to take when serial port is connected
serialPort.on('open',function() {
console.log('Port open');
});
// Setup action to take when xbee packet is received
// frame_object is emitted by the xbee.rawParser every time a complete xbee packets is received
xbee.on('frame_object', function(frame) {
//Send frame to Meteor method
Meteor.call('xbeeIncoming', frame);
//console.log('>>',frame);
});
Meteor method definition:
Meteor.methods({
xbeeIncoming: function xbeeIncoming(frame) {
console.log('xbeeData');
//var xbeeSenderAddr = frame.addr
}
});

Why are you using a method to do this. If both of them are on the server side you could use a private method instead i.e
xbeeIncoming = function(frame) {
console.log('xbeeData');
}
instead of Meteor.call('xbeeIncoming', frame); you could use xbeeIncoming(frame);
You will need to wrap the callback from xbee in a bindEnvironment (provide it can be serialized into JSON/EJSON):
var onFrame = function(frame ) {
Meteor.call('xbeeIncoming', frame);
//console.log('>>',frame);
}
xbee.on('frame_object', Meteor.bindEnvironment(onFrame));
From within this, Meteor.call should work as expected

Related

NServiceBus Router events published on Amazon SQS transport are not handled by an Azure Service Bus transport endpoint

I've been trying to get NServiceBus.Router working to allow endpoints using the AmazonSQS transport and the AzureServiceBus transport to communicate with each other. So far, I am able to get a command sent from the ASB endpoint through the router and handled by the SQS endpoint. However, when I publish an event from the SQS endpoint, it is not handled by the ASB endpoint even though I have registered the SQS endpoint as a publisher. I have no idea what I'm doing wrong, but looking at every example I can find from from the docs, it seems like it should work.
I have already tried adding another forwarding route in the reverse of what is below (SQS to ASB), but that did not solve the issue.
The endpoints and router are each running in .net 5 worker services.
I've made a sample project that reproduces the issue here, but here are some quick at-a-glance snippets that show the relevant setup:
Router Setup
var routerConfig = new RouterConfiguration("ASBToSQS.Router");
var azureInterface = routerConfig.AddInterface<AzureServiceBusTransport>("ASB", t =>
{
t.ConnectionString(Environment.GetEnvironmentVariable("ASB_CONNECTION_STRING"));
t.Transactions(TransportTransactionMode.ReceiveOnly);
t.SubscriptionRuleNamingConvention((entityType) =>
{
var entityPathOrName = entityType.Name;
if (entityPathOrName.Length >= 50)
{
return entityPathOrName.Split('.').Last();
}
return entityPathOrName;
});
});
var sqsInterface = routerConfig.AddInterface<SqsTransport>("SQS", t =>
{
t.UnrestrictedDurationDelayedDelivery();
t.Transactions(TransportTransactionMode.ReceiveOnly);
var settings = t.GetSettings();
// Avoids a missing setting error
//https://github.com/SzymonPobiega/NServiceBus.Raw/blob/master/src/AcceptanceTests.SQS/Helper.cs#L18
bool isMessageType(Type t) => true;
var ctor = typeof(MessageMetadataRegistry).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null,
new[] {typeof(Func<Type, bool>)}, null);
#pragma warning disable CS0618 // Type or member is obsolete
settings.Set<MessageMetadataRegistry>(ctor.Invoke(new object[] {(Func<Type, bool>) isMessageType}));
#pragma warning restore CS0618 // Type or member is obsolete
});
var staticRouting = routerConfig.UseStaticRoutingProtocol();
staticRouting.AddForwardRoute("ASB", "SQS");
routerConfig.AutoCreateQueues();
ASB Endpoint Setup
var endpointConfiguration = new EndpointConfiguration("ASBToSQSRouter.ASBEndpoint");
var transport = endpointConfiguration.UseTransport<AzureServiceBusTransport>();
transport.SubscriptionRuleNamingConvention((entityType) =>
{
var entityPathOrName = entityType.Name;
if (entityPathOrName.Length >= 50)
{
return entityPathOrName.Split('.').Last();
}
return entityPathOrName;
});
transport.Transactions(TransportTransactionMode.ReceiveOnly);
transport.ConnectionString(Environment.GetEnvironmentVariable("ASB_CONNECTION_STRING"));
var bridge = transport.Routing().ConnectToRouter("ASBToSQS.Router");
bridge.RouteToEndpoint(typeof(ASBToSQSCommand), "ASBToSQSRouter.SQSEndpoint");
bridge.RegisterPublisher(typeof(ASBToSQSEvent), "ASBToSQSRouter.SQSEndpoint");
endpointConfiguration.EnableInstallers();
SQS Endpoint Setup (nothing special because it doesn't need to know about the router)
var endpointConfiguration = new EndpointConfiguration("ASBToSQSRouter.SQSEndpoint");
var transport = endpointConfiguration.UseTransport<SqsTransport>();
transport.UnrestrictedDurationDelayedDelivery();
transport.Transactions(TransportTransactionMode.ReceiveOnly);
endpointConfiguration.EnableInstallers();
Any help would be greatly appreciated!
Unfortunately one of the recent SQS transport releases contains a change that makes the subscription work only by default in the context of a full NServiceBus endpoint. This feature is subscription batching.
In order for the Router to work correctly (Router does not run a full endpoint, just NServiceBus transport), you need to add this magic line to the SQS interface configuration:
settings.Set("NServiceBus.AmazonSQS.DisableSubscribeBatchingOnStart", true);
This is an undocumented flag that disables the subscription batching and allows router to complete the subscribe operations normally.
I am sorry for the inconvenience.

Can I use proxies ipv6 with CasperJS and SlimerJS?

I have a CasperJS Script duolingo.js and I run the script using a MeteorJS App using a Meteor Method like this:
// define server methods so that the clients will have access to server components
Meteor.methods({
runCasperJS: function() {
// This method call won't return immediately, it will wait for the
// asynchronous code to finish, so we call unblock to allow this client
// to queue other method calls (see Meteor docs)
this.unblock();
// run synchonous system command
var result = process_exec_sync('casperjs duolingo.js --engine=slimerjs --disk-cache=no --proxy=178.166.41.225:80 --proxy-type=HTTP');
// check for error
if (result.error) {
throw new Meteor.Error("exec-fail", "Error running CasperJS: " + result.error.message);
}
// success
return true;
}
});
I need to run the CasperJS Instance using a proxy IP V6. But I don't have any idea, the official documentations of slimerjs and casperjs did not say anything.
Here is the exact part of the code where I use an IP V4 Proxy.
var result = process_exec_sync('casperjs duolingo.js
--engine=slimerjs --disk-cache=no --proxy=178.166.41.225:80
--proxy-type=HTTP');
Thank you for your time and help.

Johnny-Five multiple Arduinos connecting, but not emitting "ready"

I'm having a little difficulty with johnny-five (Multiple Boards) ; can anyone shed some light on this for me?
I have 2 Arduinos connected and I can access them individually perfectly fine with the "var board = new five.Board()".
I can successfully connect and use them both with Cylon.js.
However, when I attempt to utilize the "new five.Boards()" it never seems emit a "ready" event so I can start coding my logic.
Using (slightly modified) johnny-five/eg/boards-multi.js
var five = require("../lib/johnny-five.js");
var boards = new five.Boards(["A", "B"]);
// Create 2 board instances with IDs "A" & "B"
boards.on("ready", function() {
// Both "A" and "B" are initialized
// (connected and available for communication)
// |this| is an array-like object containing references
// to each initialized board.
this.each(function(board) {
console.log("READY"); // NOTE: this never executes
// Initialize an Led instance on pin 13 of
// each initialized board and strobe it.
var led = new five.Led({
pin: 13,
board: board
});
led.blink();
});
});
My console shows:
1437253899028 Device(s) /dev/ttyACM1,/dev/ttyACM0
1437253899104 Connected /dev/ttyACM1
1437253899121 Device(s) /dev/ttyACM0
1437253899126 Connected /dev/ttyACM0
1437253901860 Board ID: A
1437253901862 Board ID: B
...and I wait forever and it never emits "ready"...
Note 1: I have re-uploaded the latest "StandardFirmata" on both of them several times; and they work just fine on their own.
Note 2: I have tried the exact same setup on 3 different systems (one ubuntu linux, one on Windows, and one of Raspberry PI 2B) same problem on all...
I'm not sure if I am missing something boneheaded here; however no matter what I try johnny-five just wont allow me to proceed. As I mentioned above, it seems to work perfectly with Cylon-- however, I'd rather use j5 as I've got quite a bit of code already in place I'd rather not port over to Cylon just to connect more than one Arduino to my system.
Any help would be greatly appreciated!
Update #1:
I am getting a little closer, I can address each Arduino board now. However; I am still stumped on how to properly catch the "ready" event.
var five = require('johnny-five');
var ports = [
{ id: "A", port: "/dev/ttyACM0" },
{ id: "B", port: "/dev/ttyACM1" }
];
var boards = new five.Boards(ports).on('ready', function() {
// does nothing?
console.log("THIS SHOULD TRIGGER");
});
// Waiting 5 seconds for the boards to init, instead of "ready" event.
setTimeout( function() {
console.log(boards[0].isReady);
console.log(boards[1].isReady);
}, 5000);
This ends up with the console output of:
1437268012413 Connected /dev/ttyACM0
1437268012427 Connected /dev/ttyACM1
1437268015161 Board ID: A
1437268015163 Board ID: B
true
true
....at this point, I can do the following to address the boards (within the setTimeout() of course):
var led1 = new five.Led( {
pin: 6,
board: boards[0]
});
led1.on();
var led2 = new five.Led( {
pin: 4,
board: boards[1]
});
led2.on();
Still attempting to determine why I cannot catch the elusive "ready".
Update #2:
Looks like I figured it out. It was in fact emitting ready, however I wasn't utilizing the API correctly.
Working Code:
new five.Boards(ports).on('ready', function( boards ) {
console.log( boards ); // ready emits
});
Update #3:
I think I found a bug in the library.
It seems that the following file:
node_modules/johnny-five/lib/board.js
line: 1109
If you change:
if (this.repl)
to
if (false && this.repl)
It seems to emit the "ready" event.
I've found a bug in the repl initialization, this will be fixed in the next release. The issue was a call to state.board.info(...) in Repl.prototype.initialize, where the info method was undefined as a result of an oversight during recent refactoring of the board logging and logging function definitions. This bug appeared in v0.8.85, so try npm install johnny-five#0.8.84 to resolve the issue until the next release.

Wait for async thrift requests to complete

I am invoking multiple async calls of thrift from my code. I would like to wait
for all of them to complete before going on with my next stage.
for (...) {
TNonblockingTransport transport = new TNonblockingSocket(host, port);
TAsyncClientManager clientManager = new TAsyncClientManager();
TProtocolFactory protocolFactory = new TBinaryProtocol.Factory();
AsyncClient c = new AsyncClient(protocolFactory, clientManager, transport);
c.function(params, callback);
}
// I would like to wait for all the calls to be complete here.
I can have a countdown in the callback like wait/notify and get this done. But does the thrift system allow a way for me to wait on my async function call, preferably with a timeout ?
I didnt see any in the TAsyncClientManager or in the AsyncClient. Please help.
Given that it was not possible to do this, I used the sync api client and managed the launch and wait using executors and launchAll. I am leaving this as my answer for people to have an alternative.

Signalr (1.0.0-alpha2) Hubs - Can you add client functions after connection has been started?

Using Signalr (1.0.0-alpha2), I want to know if it is possible to add client functions after a connection has been started.
Say I create my connection and grab the proxy. Then I add some Server Fired client functions to the hub to do a few things. Then I start my connection. I then want to add some more Server Fired functions to my hub object. Is this possible?
var myHub= $.connection.myHub;
myHub.SomeClientFunction = function() {
alert("serverside called 'Clients.SomeClientFunction()'");
};
$.connection.hub.start()
.done(function() {
myHub.SomeNewClientFunction = function() {
alert("serverside called 'Clients.SomeNewClientFunction()'");
}
})
This example is not realistic, but I basically want to send my 'myHub' variable to a different object after the hub is started to subscribe to new events that the original code did not care for.
Real Life Example: A dashboard with a number of different hub events (new site visits, chat message, site error). I 'subscribe' after the connection has started and then pass my hub proxy to all of my different UI components to handle their specific 'message types'. Should I create separate Hubs for these or should I be able to add more Server Fired client functions on the fly?
Yes you can. Use the .on method.
Example:
myHub.on('somethingNew', function() {
alert("This was called after the connection started!");
});
If you want to remove it later on use the .off method.
I have the exact same situation. You might want to consider adding another layout of abstraction if you're trying to call it from multiple places.
Here's a preliminary version of what I've come up with (typescript).
I'll start with the usage. SignalRManager is my 'manager' class that abstracts my debuggingHub hub. I have a client method fooChanged that is triggered on the server.
Somewhere in the module that is using SignalR I just call the start method, which is not re-started if already started.
// ensure signalR is started
SignalRManager.start().done(() =>
{
$.connection.debuggingHub.server.init();
});
Your 'module' simply registers its callback through the manager class and whenever the SignalR client method is triggered your handler is called.
// handler for foo changed
SignalRManager.onFooChanged((guid: string) =>
{
if (this.currentSession().guid == guid)
{
alert('changed');
}
});
This is a simple version of SignalRManager that uses jQuery $.Callbacks to pass on the request to as many modules as you have. Of course you could use any mechanism you wanted, but this seems to be the simplest.
module RR
{
export class SignalRManager
{
// the original promise returned when calling hub.Start
static _start: JQueryPromise<any>;
private static _fooChangedCallback = $.Callbacks();
// add callback for 'fooChanged' callback
static onfooChanged(callback: (guid: string) => any)
{
SignalRManager._fooChangedCallback.add(callback);
}
static start(): JQueryPromise<any>
{
if (!SignalRManager._start)
{
// callback for fooChanged
$.connection.debuggingHub.client.fooChanged = (guid: string) =>
{
console.log('foo Changed ' + guid);
SignalRManager._fooChangedCallback.fire.apply(arguments);
};
// start hub and save the promise returned
SignalRManager._start = $.connection.hub.start().done(() =>
{
console.log('Signal R initialized');
});
}
return SignalRManager._start;
}
}
}
Note: there may be extra work involved to handle disconnections or connections lost.

Resources