AWS IOT : Cannot Register with shadow - aws-iot

I have created a thing in AWS IoT called RasberryPi and I am trying to register with its shadow using the following code :
var awsIot = require('aws-iot-device-sdk');
var thingShadows = awsIot.thingShadow({
keyPath: "./certs/private.pem.key",
certPath: "./certs/certificate.pem.crt",
caPath: "./certs/root-CA.crt",
clientId: "RasberryPi1",
region: "eu-west-1",
port: "8883",
debug: true
});
thingShadows.on('connect', function() {
console.log('connected');
thingShadows.register( 'RasberryPi1', function() {
console.log('registered');
...
I successfully connect but I never register. That is, the second console.log statement never runs. Can anybody please advise on my mistake? I'm very new to AWS IoT and my mistake is probably very basic.
Many thanks

It may be really confusing but it is because of docs. You are probably following examples like here: https://github.com/aws/aws-iot-device-sdk-js#thing-shadow-class
//
// After connecting to the AWS IoT platform, register interest in the
// Thing Shadow named 'RGBLedLamp'.
//
thingShadows.register( 'RGBLedLamp', function() {
// Your code here
}
but when you read the docs here: https://github.com/aws/aws-iot-device-sdk-js#awsiotthingshadowregisterthingname-options-callback- you can see that the register function takes callback not as second argument but as third(!)
Just call it like this:
thingShadows.register( 'RGBLedLamp', {}, function() {
// Your code here
}
and it'll work like a charm

Related

Dart AppEngine Headers already sent when using Futures

I am using AppEngine and wrote a server application in Dart. Since the gcloud API is using Futures for pretty much everything, I make use of them as well. The problem however, once I start using Futures, a BadStateException is thrown. See the two examples below.
Working server
runAppEngine((HttpRequest request) {
request.response
..writeln('Hello world')
..statusCode = HttpStatus.OK
..close();
}, port: port);
Output:
Hello world
Not working server: Headers already sent
Future _asyncTask(HttpRequest request) {
return new Future(() {
request.response
..writeln('Hello world')
..statusCode = HttpStatus.OK; // causes BadStateException
}).catchError((e) {
request.response.writeln(e.toString());
}).whenComplete(() {
request.response.close();
});
}
runAppEngine((HttpRequest request) {
return _asyncTask(request);
}, port: port);
Output:
Hello world Bad state: HTTP headers were already sent.
I would like to use Futures but for some reasons, I just cannot get rid of the BadStateException. Can someone point me to what I am doing wrong?
Oh well, seems like I found the bug. I was looking for a fix to this problem all day and now that I ask here, I find the problem five minutes later.
Anyhow, I hope this answer helps people with the same problem.
The problem is that with writing to the response, headers are set implicitly. Hence, once you call writeln(String) you cannot set any headers afterwards anymore.
The reason, that there is no error logged in the first server code is, that there is simply no logic to log errors, but it is as wrong as the second one.
Here is the correct way of doing it:
Future _asyncTask(HttpRequest request) {
return new Future(() {
request.response
..statusCode = HttpStatus.OK
..writeln('Hello world');
}).catchError((e) {
request.response.writeln(e.toString());
}).whenComplete(() {
request.response.close();
});
}
runAppEngine((HttpRequest request) {
return _asyncTask(request);
}, port: port);
As you can see, the problem is fixed by sending the headers first.

Expose object fron Angularjs App to Protractor test

I am writing end-to-end tests for my AngularJS-based application using Protractor. Some cases require using mocks to test - for example, a network connection issue. If an AJAX request to server fails, the user must see a warning message.
My mocks are registered in the application as services. I want them to be accessible to the tests to write something like this:
var proxy;
beforeEach(function() { proxy = getProxyMock(); });
it("When network is OK, request succeeds", function(done) {
proxy.networkAvailable = true;
element(by.id('loginButton')).click().then(function() {
expect(element(by.id('error')).count()).toEqual(0);
done();
});
});
it("When network is faulty, message is displayed", function(done) {
proxy.networkAvailable = false;
element(by.id('loginButton')).click().then(function() {
expect(element(by.id('error')).count()).toEqual(1);
done();
});
});
How do I implement the getProxyMock function to pass an object from the application to the test? I can store proxies in the window object of the app, but still do not know how to access it.
After some reading and understanding the testing process a bit better, it turned to be impossible. The tests are executed in NodeJS, and the frontend code in a browser - Javascript object instances cannot be truly shared between two different processes.
However, there is a workaround: you can execute a script inside browser.
First, your frontend code must provide some sort of service locator, like this:
angular.module('myModule', [])
.service('proxy', NetworkProxy)
.run(function(proxy) {
window.MY_SERVICES = {
proxy: proxy,
};
});
Then, the test goes like this:
it("Testing the script", function(done) {
browser.executeScript(function() {
window.MY_SERVICES.proxy.networkAvailable = false;
});
element(by.id('loginButton')).click().then(function() {
expect(element.all(by.id('error')).count()).toEqual(1);
done();
});
});
Please note that when you use executeScript, the function is serialized to be sent to browser for execution. This puts some limitations worth keeping in mind: if your script function returns a value, it is a clone of the original object from browser. Updating the returned value will not modify the original! For the same reason, you cannot use closures in the function.

SignalR: How to add client call after the hub is started?

First off, I just started trying to add SignalR 2 to my existing Angular SPA project.
I have a main controller which starts the hub right away that is feeding some messages to the client. Inside, I have several sub pages and each could subscribe to a different hub for services. The problems is that the client doesn't receive message because it is hooked up after the hub is already started in the main controller.
As a test, if I comment out the hub start in the main controller, the one in the sub controller works fine.
From what I read, it is by design that you have to hook up all client calls before starting the hub. I don't understand...if it is a service, I should be able to subscribe or unsubscribe anytime after the hub is started. Why not? How to workaround?
Because no response in the 12 hours (which is quite unusual in so), I had to dig around myself. I think, I was misled by the answers from SO on related questions that you have to subscribe all client call before starting the connection, as mentioned e.g. here. I found in Hubs API Guide, one section says
Define method on client (without the generated proxy, or when adding
after calling the start method)
So, it is possible to add client method after connection is started. The trick is to use so-called "without the generated proxy". That limitation is for "with generated proxy".
The following is my working example taken from SignalR get started tutorial.
This is the main controller using "with generated proxy":
$.connection.statusHub.client.updateStatus = function (status) {
$scope.status = status;
$scope.$apply();
}
$.connection.hub.start();
This is in a subcontroller using "without generated proxy":
var connection = $.hubConnection();
var proxy = connection.createHubProxy('stockTickerHub');
proxy.on('updateStockPrice', function (stock) {
var st = $scope.stocks.firstOfKey(stock.symbol, 'symbol');
st.lastPrice = stock.lastPrice;
$scope.$apply();
});
var hub = $.connection.stockTickerHub;
connection.start().done(function () {
hub.server.getAllStocks().done(function (stocks) {
$scope.stocks = stocks;
});
});
Note that it doesn't work if I use "with generated proxy" in the subcontroller like this:
var hub = $.connection.stockTickerHub;
hub.client.updateStockPrice = function (stock) {
var st = $scope.stocks.firstOfKey(stock.symbol, 'symbol');
st.lastPrice = stock.lastPrice;
$scope.$apply();
};
$.connection.hub.start().done(function () {
hub.server.getAllStocks().done(function (stocks) {
$scope.stocks = stocks;
});
});
To prove the limitation of "with generated proxy" mode, this code works if I comment out the one in the main controller.
By the way, I was so confused by the term with or without generated proxy in the Guide, and in both cases, it is still called xxxProxy. Can't they find a better name? Or somebody has an explanation?

How to check user has internet connection, using angularJs

When an user attempts to log in without Internet connection, I just need to check whether he/she is connected to internet or not.
I tried the following code :
if (status == '404') {
$scope.error="No internet connection";
return false;
}
But this status 404 comes even when my Web Service failed to connect. I need to differentiate both, if is the user's internet connection issue or the Web Service connection issue.
Using navigator.onLine
You can use navigator.onLine and wrap it on a helper variable, like this (Credits to this answer)
myApp.run(function($window, $rootScope) {
$rootScope.online = navigator.onLine;
$window.addEventListener("offline", function () {
$rootScope.$apply(function() {
$rootScope.online = false;
});
}, false);
$window.addEventListener("online", function () {
$rootScope.$apply(function() {
$rootScope.online = true;
});
}, false);
});
and then watch it in the controller:
$scope.$watch('online', function(newStatus) { ... });
But that just serves as a dirty check to know if the PC is actually connected to a network, not meaning that the internet is working.
Using a fake AJAX request
You can mock a service that does a fake request to a browser (warning: non-tested code below)
myApp.service('Internet', function($http){
this.IsOk = function () {
return $http({ method: 'HEAD', url: '/' + window.location.hostname + "/?rand=" + Math.floor((1 + Math.random()) * 0x10000) })
.then(function(response) {
var status = response.status;
return status >= 200 && status < 300 || status === 304;
});
}
});
And then use something in this context:
myApp.controller('TestController', function(Internet){
Internet.IsOn().then(function(isok){
if(isok) {...} else {...}
});
});
Code for request mocking in this link.
Also note that it will not work using localhost, because the server will work even when disconnected to the internet.
Taken from MDN's summary of NavigatorOnLine.onLine.
Browsers implement this property differently.
In Chrome and Safari, if the browser is not able to connect to a local
area network (LAN) or a router, it is offline; all other conditions
return true. So while you can assume that the browser is offline when
it returns a false value, you cannot assume that a true value
necessarily means that the browser can access the internet. You could
be getting false positives, such as in cases where the computer is
running a virtualization software that has virtual ethernet adapters
that are always "connected." Therefore, if you really want to
determine the online status of the browser, you should develop
additional means for checking. To learn more, see the HTML5 Rocks
article, Working Off the Grid.
In Firefox and Internet Explorer, switching the browser to offline
mode sends a false value. All other conditions return a true value.
You can see changes in the network state by listening for the events
on window.onOnline and window.onOffline.
You can access that information via window.navigator.onLine, but as the documentation states, it's very inconsistent cross-browser.
You can also listen for changes in status using window.addEventListener as follows:
window.addEventListener("offline", function(e) {alert("offline");})
window.addEventListener("online", function(e) {alert("online");})
There is a JavaScript property, navigator.onLine, it returns a Boolean value that specifies wether the browser is in online mode or offline mode.
The navigator object contains information about the user's browser.
It is supported in all major browsers, so you sholdn't have any problem at all.

Get the current browser name in Protractor test

I'm creating users in some test. Since it is connected to the backend and create real users I need fixtures. I was thinking of using the browser name to create unique user. However, It has proven to be quite difficult to get to it...
Anyone can point me in the right direction?
Another case of rubber ducking :)
The answer was actually quite simple.
in my onPrepare function I added the following function and it works flawlessly.
browser.getCapabilities().then(function (cap) {
browser.browserName = cap.caps_.browserName;
});
I can get access the name in my test using browser.browserName.
This has changed in version of protractor starting from 3.2 (selenium webdriver 2.52)
Now one should call:
browser.driver.getCapabilities().then(function(caps){
browser.browserName = caps.get('browserName');
}
If you want to avoid the a browser, you may want to do this:
it('User should see a message that he has already been added to the campaing when entering the same email twice', function () {
browser.getCapabilities().then(function (capabilities) {
browserName = capabilities.caps_.browserName;
platform = capabilities.caps_.platform;
}).then(function () {
console.log('Browser:', browserName, 'on platform', platform);
if (browserName === 'internet explorer') {
console.log('IE Was avoided for this test.');
} else {
basePage.email.sendKeys('bruno#test.com');
console.log('Mande el mail');
basePage.subscribe.click().then(function () {
basePage.confirmMessage('Contact already added to target campaign');
});
}
});
});

Resources