AWS DynamoDB query top 5 scores for country

Let’s take a look at how to query top 5 scores from AWS DynamoDB, let say we have some top scores table and want to get top 5 performers for the specific country. What we also need is not to waste the network resources, that’s why we will specify what exact fields we need to fetch from server – with help of projectionExpression.
Moreover let’s take a look at how to deal with the following error:
com.amazon.coral.validate#ValidationException”,”message”:”Invalid ProjectionExpression: Attribute name is a reserved keyword; reserved keyword: name”

it could be solved by adding reserved words to the expressionAttributeNames, e.g. instead of

queryExpression.projectionExpression = "userId,challenge,country,name,total"

where name and total are reserved words let’s do the following

queryExpression.expressionAttributeNames = [
            "#n": "name",
            "#t": "total",
        ]
queryExpression.projectionExpression = "userId,challenge,country,#n,#t"

That approach will eliminate the ValidationException – reserved keyword; reserved keyword error.

Here’s the whole method
Continue reading “AWS DynamoDB query top 5 scores for country”

Social Share Toolbar

IoT: raspberry pi 3 how to blink led from iPhone

Internet of Things: raspberry pi 3 – how to blink led from iPhone?

Here’s a tech stack:
– raspberry pi 3 + led
– node-red hosted in AWS/anywhere – should be available in internet
– node js script on raspberry pi connected to node-red via web socket
– swift/ios app which makes http requests to node-red

Let’s start from node-red configuration (it’s a really cool tool for wiring together hardware devices, APIs and online services). All we need is to have “http GET” input, let specify the following path “/mmled/status” for it. and we want to wire it with Output/”Listen on” “web socket” with “/ws/mmled” path. We might also want to add “pay load” node.
So with several “debug” nodes (convenient way to debug our endpoint) it should look something like this:

nodered

At this point if we will GET https://{nore-red-host}/mmled/status?value=1 we will see the following things:
– {“value”: 1} in the debug panel
– the same message we will get in case if we are listening the “wss://{nore-red-host}/ws/mmled” socket.

Let’s check it, here is the node js “server” script which we going to start like “sudo node server” on raspberry pi:

var W3CWebSocket = require('websocket').w3cwebsocket;
var Gpio = require('onoff').Gpio;
var led = new Gpio(17, 'out');  
var client = new W3CWebSocket('wss://{node-red-host}/ws/mmled');
 
client.onerror = function() {
    console.log('Connection Error');
};
 
client.onopen = function() {
    console.log('WebSocket Client Connected');
};
 
client.onclose = function() {
    console.log('echo-protocol Client Closed');
    if (led) led.unexport();
};
 
client.onmessage = function(e) {
    if (typeof e.data === 'string') {
        console.log("Received: '" + e.data + "'");
        try {
            var data = JSON.parse(e.data);
            var newValue = parseInt(data.value);
            console.log('got new value = ' + newValue);
            led.writeSync(newValue);
        } catch (ex) {
            console.log('invalid JSON in e.data');
        }
    }
};

Ok, let’s digg into the magic, first of all what is

var Gpio = require('onoff').Gpio;
var led = new Gpio(17, 'out');

if you will google “raspberry pi 3 pins” you’ll find where “GPIO 17” – you basically need to connect it to resistor + led + GND
after that you’ll have a chance to turn led on with this line – “led.writeSync(1);” and turn it off with “led.writeSync(0);“. So the circuit is the following:
raspberry pi [DPIO 17 pin] -> resistor -> led -> raspberry pi [GND pin]

Everything else we need to connect and listen socket and to react on the value change. run the script with

sudo node server

and try to GET https://{node-red-host}/mmled/status?value=1
and and try to GET https://{node-red-host}/mmled/status?value=0 to toggle the led. It’s awesome, at this step you can enable/disable your LED from internet!

Let’s create a new “single view” xcode project and drop a “switch” UI element on the view. Go to “Assistant editor” and bind the switch’s “action” to the code. Here is the controller’s code:

import UIKit
 
class ViewController: UIViewController {
 
    let ledUrl = "https://{node-red-host}/mmled/status"
 
    func setLed(status: Bool) {
        let finalUrl = ledUrl + "?value=" + (status ? "1" : "0")
        print("final url = " + finalUrl)
        let nsUrl = NSURL(string: finalUrl)
        let task = NSURLSession.sharedSession().dataTaskWithURL(nsUrl!) {(data, response, error) in
            print(NSString(data: data!, encoding: NSUTF8StringEncoding))
        }
 
        task.resume()
    }
 
    @IBAction func onChange(sender: UISwitch) {
        setLed(sender.on);
    }
 
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
 
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

It’s just sending GET request with the value 1 or 0 on toggle/switch change. That’s it, if you’ll run the app and toggle the switch you’ll see the message in the “debug” node, and you’ll see your LED blinking which is Awesome! You might go further and replace led with relay+real lamp, but it’s a different story.

Here’s an EPIC demo video, just for fun and self-motivation.

Social Share Toolbar

WatchOS 2 tutorial: Activity Ring – WKInterfaceActivityRing

Just a quick example how to use WKInterfaceActivityRing and HKActivitySummary to show Activity Ring.

Simulator Screen Shot Jun 7, 2016, 8.58.27 PM

Go ahead and drag “Activity Ring” on your Interface Controller, use Assistant Editor to add Outlet to your Controller, e.g.

@IBOutlet var activityRing: WKInterfaceActivityRing!

All you need to set up Activity Ring values is to create and initialize HKActivitySummary, here is the sample code (for simplicity we are going to use the same values for all the rings)

let summary = HKActivitySummary()
let value: Double = 2
let goal: Double = 10
 
summary.activeEnergyBurned = HKQuantity(unit: HKUnit.kilocalorieUnit(), doubleValue: value)
summary.activeEnergyBurnedGoal = HKQuantity(unit: HKUnit.kilocalorieUnit(), doubleValue: goal)
 
summary.appleExerciseTime = HKQuantity(unit: HKUnit.minuteUnit(), doubleValue: value)
summary.appleExerciseTimeGoal = HKQuantity(unit: HKUnit.minuteUnit(), doubleValue: goal)
 
summary.appleStandHours = HKQuantity(unit: HKUnit.countUnit(), doubleValue: value)
summary.appleStandHoursGoal = HKQuantity(unit: HKUnit.countUnit(), doubleValue: goal)
 
activityRing.setActivitySummary(summary, animated: true)

That’s pretty much it.

Social Share Toolbar

swift: How to render a UIView to a UIImage

You can render any UIView into UIImage in just several lines of code. Never mind subviews – that will be handled automatically. Here’s the code:

 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, 0)
    view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

For sure you can extend UIImage for convenience

import UIKit
 
 
extension UIImage {    
    convenience init(view: UIView) {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, 0)
        view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(CGImage: image.CGImage!)
    }
}

After that you’ll need just:

 
    UIImage(view: someChartView)

That’s it!

P.S. Available from iOS 7.0

Social Share Toolbar

AWS Mobile hub, swift and dynamoDB

If you will google “backend for ios application” or “backend for swift application” you can notice that Amazone Mobile Hub will be in the top results, articles whatever, the easiest way to start your backend right now is for sure https://aws.amazon.com/mobile especially if you already familiar with aws. The wizard is quite well and detailed, it will guide you through the process and will even generate sample project YourApp-aws-my-sample-app-ios-swift which will use the backend which you have just configured in the web.
I believe you can play with wizard by yourself and reach even the point when you will copy-paste all AWS stuff to you project – wizard greatly describe even this part. I just want to highlight several steps/moments which were not very obviously for me, and show the example how to use mobile hub even easier w/o copying all the code from AWS – I mean tables, helpers, and all that swift stuff, you will need only One file – aws data model, and that’s it, you are all set to make backend requests.

Please start with completing this wizard https://aws.amazon.com/mobile
Several things they forgot to mention in the step “Use MySampleApp as an Example”:
1. While copying settings from Sample’s Info.plist to yours one, additionally copy “App Transport Security Settings”.
001
It is easy to forget and it’s really required to allow your app to make http requests to aws instances
2. On the step “Add a Run Script phase to your project” you need to add “bash “${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/AWSCore.framework/strip-frameworks.sh” line to the “Build Phases”.
It’s vital to have “Run script” section under the “Embed frameworks” and basically all other, just drag it to the bottom, so you can avoid “…Frameworks/AWSCore.framework/strip-frameworks.sh: No such file or directory” error during the Build of your app.
So drag it down like that
002
and try to clean and build your project once again – should be fine in case if you had such an error.

Read further if you have successfully finished all wizards steps and if you have your app up and running and connected with aws backend.

Lets say we want to create a new table for collecting Feedback, we just need to post the “Feedback” and that’s it, let go ahead and create a new table in mobilehub, so I clicked to “Configure” section, than to NoSql Databases and choose “Add new table” option on the bottom, here is my scheme:
003
Ensure that in the “Queries this table can perform.” you have “Find all items with deviceId = ABC” option, otherwise you will have only one Feedback from one device, it will be the latest one.

You can try to download the latest version of Sample App, but eventually the only thing you nee is the table ID which looks like this “AppName-mobilehub-xxxxxxxxxx-Feedback”. You don’t really need those humongous Tables and Helper classes, the only one thing you might want to copy-paste from the latest Sample is the Feedback.swift which is data model for AWS DynamoDB, it looks like this (Feedback.swift):

//...
 
import Foundation
import UIKit
import AWSDynamoDB
class Feedback: AWSDynamoDBObjectModel, AWSDynamoDBModeling {
 
    var _deviceId: String?
    var _appName: String?
    var _text: String?
    var _userContact: String?
    var _date: String?
 
    class func dynamoDBTableName() -> String {
        return "AppName-mobilehub-xxxxxxxxxxx-Feedback"
    }
 
    class func hashKeyAttribute() -> String {
        return "_deviceId"
    }
 
    class func rangeKeyAttribute() -> String {
        return "_date"
    }
 
    override class func JSONKeyPathsByPropertyKey() -> [NSObject : AnyObject] {
        return [
            "_deviceId" : "deviceId",
            "_appName" : "appName",
            "_text" : "text",
            "_userContact" : "userContact",
            "_date" : "date",
        ]
    }
}

Ok, we are ready to post the feedback, here is all we need:

    func postFeedback(contact: String, text: String, completionHandler: (error: NSError?) -> Void) {
        let feedback = Feedback()
        feedback._deviceId = Identity.getUserUniqueId() // AWS Identity
        feedback._date = String(NSDate())
        feedback._appName = "AppName" // Just in case if you'll want to use this table from several apps.
        feedback._userContact = contact
        feedback._text = text
 
        insertFeedbackWithCompletionHandler(feedback, completionHandler: completionHandler)
    }
 
    // MARK: AWS Methods
    internal func insertFeedbackWithCompletionHandler(item: Feedback, completionHandler: (error: NSError?) -> Void) {
        let objectMapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
 
        objectMapper.save(item, completionHandler: {(error: NSError?) -> Void in
            dispatch_async(dispatch_get_main_queue(), {
                completionHandler(error: error)
            })
        })
    }

So this is basically it, go ahead and run you app and it should work (obviously you had to create a UI and call this method on your own). You might noticed this line “Identity.getUserUniqueId()” just in case here is what’s under the hood:

    func getUserUniqueId() -> String {
        let identityManager = AWSIdentityManager.defaultIdentityManager()
        return identityManager.identityId ?? TEST_ID
    }

This is it, AWS mobilehub is very easy and way to create a backend for you iso app, I still had no chance to push it’s limits and I’m sure that there is a price for such a high-level abstraction but it’s very easy for simple use cases. May be I’ll post some results on my researches on it’s performance or dealing with edge cases. It was kind of overview of this new technology.

P.S. To check out the content of your DynamoDB go here https://console.aws.amazon.com/dynamodb/home?region=us-east-1#tables: choose the right region, click to “…-Feedback” table and click “Items” tab, here you can see all the items from your database and even scan or query them.

Social Share Toolbar

My slides from UxPeople.by

My slides from http://uxpeople.by/http://www.slideshare.net/mikitamanko/mikita-manko-at-u-xpeopleby

Social Share Toolbar

Chrome remote debugging on ios 6 (iphone 5)

Let’s dig into chrome remote debugging on ios 6 (iphone 5)

1. First of all we need to configure fiddler as a proxy
open fiddler->tools->fiddler options-> connections: set port to 8888, check “allow remote computers to connect” (google how to set up fiddler proxy for details)

2. configure iphone:
open command line on your desktop and type “ipconfig” to figure out your local ip
open settigns on iphone->wi-fi->current active network settings: scroll down, set proxy to manual and fill in proxy ip (ip from previous point and port 8888)

3. check that iphone is using your desktop as a proxy
just open any page in chrome on iphone and check fiddler out

4. install nodejs (click install here http://nodejs.org/)
check installation with the following commands:

node -v

I got something like – “v0.10.17”
then check that npm has been also installed

npm -v

I got something like 0 “1.3.8”

5. configure local server for files
e.g. we can add to hosts file “127.0.0.1 mydomain.com”
and set up new IIS site for this domain, so we got this page “http://mydomain.com/mypage.html” mapped on local env

6. configure local page – we need to add this script to our local page

<script src="http://mydomain:8080/target/target-script-min.js#anonymous"></script>

7. run weinre – run from console

weinre --boundHost mydomain.com

should respond something like “2013-08-26T13:31:58.109Z weinre: starting server at http://mydomain.com:8080”

8. open debugger
open this link http://mydomain.com:8080/client/#anonymous

9. open page on a mobile device – open page with weinre script – http://mydomain.com/mypage.html

10. check out desktop chrome with opened http://mydomain.com:8080/client/#anonymous – this debugger should be attached to the page opened on iphone

11. Thats all

P.S.
some helpful links:
http://people.apache.org/~pmuellr/weinre/docs/latest/Installing.html
http://people.apache.org/~pmuellr/weinre/docs/latest/Running.html

Social Share Toolbar

My talk at Mobile Optimized conference

Last friday, I talked about Kendo UI at Mobile Optimized conference in webnotbombs.net section.

My slides http://www.slideshare.net/mikitamanko/kendo-ui-mikita-manko-at-mobile-optimized

Social Share Toolbar