Since some weeks ago I have been trying to find a way of buying a Surface 2 Pro 256GB to definitively replace my development laptop. Some videos I have seen on YouTube like having 4 external displays brought my attention and after asking Joe Brinkman and Alberto Diaz about their experience working with the tablet as a dev machine both answered that definitively can replace my laptop (of course with the docking station). The final decision was taken after seeing another thread in the Surface Forums about the gaming experience like playing Call of Duty Ghosts on a Surface Pro 2.If that beast can move those types of games, for sure that can replace my current laptop.
And the problem started…
Looking for a Surface 2 on the stores
I have been trying to find a Surface 2 Pro 256GB in order to have the 8GB RAM in almost all the stores on Internet, and was really surprising that this model is Out of Stock in almost all of them. When finally found that the Microsoft Store at UK, I started to evaluate the problem of not getting the correct warranty if I’m in another country, different AC plugs than Spain, etc. The price it’s not low so the risk of having a problem without a store/warranty was not an option.
So the final decision was to buy it on Spain but same problem. Out of stock. I call the Microsoft Store and they didn’t know about when they could arrive. Bad thing.
I’m a developer, I don’t like doing things twice
I have been checking the Microsoft Store website twice a day since two weeks ago, and I was starting to be tired of doing it. So I was wondering if I could automate the process and receive some type of alert when the devices were in stock again. And then I found the how to create my new minion.
Looking into how the Store page works, I noticed that a GET WebAPI call is done to show the availability of the product:
More interesting was the result of that WebAPI call, since it’s an XML with the stock status for that product:
Idea! Idea! Idea!
If I didn’t want to check the website twice a day, what I would like was just to receive an alert of when the devices were in stock again. Would be nice to receive an e-mail on such event, and would love get an SMS on my mobile!
I always compare Azure and other cloud services like a Lego store. The pieces are there to build solutions, you only need to know about them. So let’s put some pieces in place:
- Azure Mobile Services: in order to have a scheduled task looking for the device stock at the store. There are other options but the scheduler provided by Mobile Services is sufficient for this purpose and also free when using 1 scheduled task;
- SendGrid: in order to receive an e-mail notification for stock changes. Again, there are other options but SendGrid offers a free tier for Azure subscribers that allows to accomplish this also for free;
- Twilio: in order to receive SMS notifications for stock changes. Again, you can signup Twilio for free –no credit card needed- and send up to 1000 SMS (Azure subscribers get $10 when adding credit later to Twilio).
Cool, I love free stuff.
Adding some code to a scheduled task
So with the pieces in mind, the API keys from SendGrid and Twilio in my Notepad++, I started to create an empty Azure Mobile service through the management console.
The only thing inside the mobile service is just an scheduled task configured to run once per hour (my minions must work harder than me!!).
Finally the script code for the scheduler task. Note that I have hidden the API keys, e-mails and phone numbers:
function CheckAvailability() {
try {
var url = "http://surface.microsoftstore.com/store/mseea/es_ES/DisplayPage/id.ProductInventoryStatusXmlPage/productID.287012200?_=13";
var request = require("request");
request(url, function(error, r, body) {
if (error) { return console.error(error); }
if (r.statusCode != 200) { return console.error(r); }
var xml2js = require('xml2js');
var parser = new xml2js.Parser();
parser.parseString(body, function (err, result) {
if (err) { return console.error(err); }
if (result.InventoryStatusResponse.availableQuantity != "0") {
sendNotifications(result.InventoryStatusResponse);
} else {
console.warn(result.InventoryStatusResponse.inventoryStatus);
}
});
});
}
catch(e) {
console.error(e);
}
}
var SendGrid = require('sendgrid').SendGrid;
function sendNotifications(inventoryStatusResponse) {
sendSMS(inventoryStatusResponse);
sendEMail(inventoryStatusResponse);
}
function sendSMS(inventoryStatusResponse) {
var httpRequest = require('request');
var account_sid = "Your_Twilio_Account_SID_here";
var auth_token = "Your_Twilio_Auth_Token_here";
var from = "+345550000";
var to="+3465550001";
var message = 'The new Surface 2 Pro 256GB is now available at Microsoft Store. Units available: '
+ inventoryStatusResponse.availableQuantity;
// Create the request body
var body = "From=" + from + "&To=" + to + "&Body=" + message;
// Make the HTTP request to Twilio
httpRequest.post({
url: "https://" + account_sid + ":" + auth_token +
"@api.twilio.com/2010-04-01/Accounts/" + account_sid + "/Messages.json",
headers: { 'content-type': 'application/x-www-form-urlencoded' },
body: body
}, function (err, resp, body) {
if (err) { return console.error(err); }
console.log(body);
});
}
function sendEMail(inventoryStatusResponse) {
console.log('Surface 2 Pro 256GB available at Microsoft Store. Units available: '
+ inventoryStatusResponse.availableQuantity + '. Sending notifications...');
var api_user = 'Your_SendGrid_ApiUser';
var api_key = 'Your_SendGrid_ApiKey';
var sendgrid = new SendGrid(api_user, api_key);
sendgrid.send({
to: 'foo@mydomain.com',
from: 'bar@mydomain.com',
subject: 'Surface 2 Pro 256GB available at Microsoft Store!',
text: 'The new Surface 2 Pro 26GB is now available at Microsoft Store. Units available: '
+ inventoryStatusResponse.availableQuantity
}, function(success, message) {
// If the email failed to send, log it as an error so we can investigate
if (!success) {
console.error(message);
}
else {
console.log('Email notification sent!');
}
});
}
Finally, by commenting the line checking for the availableQuantity != “0”, I got my initial notifications arriving to my devices:
Conclusion
The implementation shown above can be considered a proof of concept –BTW, probably I should not use the Store WebAPI without Microsoft confirmation- of things you can you can do by integrating different cloud services available today, and start using them for free.
The world has changed and is now cloud-connected.
Have you started to think cloud?
Saludos y Happy Coding!