Testing go 1.5 cross compilation on raspberry pi

August 29, 2015

I'm so excited with the new release of golang. One particular feature is now very easy to build for multiple architecture. If you seen my other posts, I also like to tinker with my raspberry-pi. On my previous project I use either ruby or python for building some stuff. One annoying thing is dependency, setup and compilation is usually quite slow. Would be cool if I could just create some stuff in desktop and just scp the binary to pi and everything should work!

There is this nice article that explain the process. Let's start there and create simple application

12345678910
package main

import (
"fmt"
"runtime"
)

func main() {
fmt.Printf("Hello. I'm running %s on %s architecture\n", runtime.GOOS, runtime.GOARCH)
}

Let's try to build it

12345
# create binary called 'main' for raspberry-pi (1gen)
$ env GOOS=linux GOARCH=arm GOARM=6 go build main.go

# transfer the binary to pi
$ scp main pi:

Now, crossing my finger, and run it on my pi

12345
$ ssh pi

pi@raspbmc:~$ ./main
Hello. I'm running linux on arm architecture
pi@raspbmc:~$

Holy crap, it's that easy. I'm excited. Let's see if go routine works

12345678910111213141516171819202122232425262728293031323334
package main

import (
"fmt"
"sync"
)

func main() {
var wg sync.WaitGroup
nWorker := 2
c := make(chan string)

// write 10 message to channel c
go func() {
defer close(c)
for i := 0; i < 10; i++ {
c <- fmt.Sprintf("item sequence %d", i)
}
}()

// create n worker to read from channel c
for i := 0; i < nWorker; i++ {
wg.Add(1)
go func(worker int) {
for msg := range c {
fmt.Printf("worker %d: msg %s\n", worker, msg)
}
wg.Done()
}(i)
}

wg.Wait()
fmt.Println("That's super awesome!!, cee ya!")
}

Again, build and scp, and cross some more fingers

1234567891011121314
@raspbmc:~$ ls -alh main
-rwxr-xr-- 1 pi pi 1.9M Aug 29 18:08 main
pi@raspbmc:~$ ./main
worker 1: msg item sequence 0
worker 0: msg item sequence 1
worker 1: msg item sequence 2
worker 0: msg item sequence 3
worker 0: msg item sequence 4
worker 0: msg item sequence 5
worker 0: msg item sequence 6
worker 0: msg item sequence 7
worker 0: msg item sequence 8
worker 1: msg item sequence 9
That's super awesome!!, cee ya!

Super awesome indeed, it just works!. Oh and the binary is not that big 1.9M considering it statically include the library.

Hmm let's try something fun that fiddle with the gpio pin. Let's create something that what raspberry-pi made for.. blinking led :p

There is already library. Let's starts there.

12345678910111213141516171819202122232425262728293031323334353637383940414243
package main

import (
"fmt"
"os"
"os/signal"
"time"

"github.com/davecheney/gpio"
"github.com/davecheney/gpio/rpi"
)

func main() {
// set GPIO25 to output mode
pin, err := gpio.OpenPin(rpi.GPIO25, gpio.ModeOutput)
if err != nil {
fmt.Printf("Error opening pin! %s\n", err)
return
}

// turn the led off on exit
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for _ = range c {
fmt.Printf("\nClearing and unexporting the pin.\n")
pin.Clear()
pin.Close()
os.Exit(0)
}
}()

dance(pin)
}

func dance(pin gpio.Pin) {
for {
pin.Set()
time.Sleep(500 * time.Millisecond)
pin.Clear()
time.Sleep(500 * time.Millisecond)
}
}

Dayuumm.. It's that easy. No more pip install or bundle install on pi. Just scp the binary!

Of course we've got this far, we must try to control it remotely via HTTP.


1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
package main

import (
"fmt"
"net/http"
"os"
"os/signal"
"time"

"github.com/davecheney/gpio"
"github.com/davecheney/gpio/rpi"
)

// channel to control start blinking or not
var ctrlChan = make(chan bool)

func main() {
// set GPIO25 to output mode
pin, err := gpio.OpenPin(rpi.GPIO25, gpio.ModeOutput)
if err != nil {
fmt.Printf("Error opening pin! %s\n", err)
return
}

// turn the led off on exit
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for _ = range c {
fmt.Printf("\nClearing and unexporting the pin.\n")
pin.Clear()
pin.Close()
os.Exit(0)
}
}()

go dance(pin, ctrlChan)
ctrlChan <- true

// http listen
http.HandleFunc("/dance", danceHandler)
http.ListenAndServe(":8080", nil)
}

func dance(pin gpio.Pin, ctrlChan chan bool) {
enabled := false
for {
select {
case val := <-ctrlChan:
// got value from danceHandler via the channel
fmt.Printf("dancing? %+v\n", val)
enabled = val
default:
if enabled {
pin.Set()
time.Sleep(500 * time.Millisecond)
pin.Clear()
time.Sleep(500 * time.Millisecond)
}
}
}
}

func danceHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Received request")
s := r.URL.Query().Get("s")
ctrlChan <- s == "1" // tell dance to enable or not
}

Look at that. All it takes to do that is just 67 lines of code. The main logic just about 31 lines. That's including the fancy dancing blinking. No framework, only gpio dependency. Everything else is go stdlib.

Ok, let's do one other thing. The reverse! Trigger something when button is pressed. For this let's just use websocket, and see how hard it is to implement this. What this mean that if you have websocket client (web browser) you could listen to event and stream it directly from your raspberry-pi to your computer.


12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
package main

import (
"bufio"
"fmt"
"net/http"
"os"
"os/signal"
"time"

"github.com/davecheney/gpio"
"github.com/davecheney/gpio/rpi"
"golang.org/x/net/websocket"
)

// channel to control start blinking or not
var ctrlChan = make(chan bool)

func main() {
// set GPIO25 to output mode
pin, err := gpio.OpenPin(rpi.GPIO25, gpio.ModeOutput)
if err != nil {
fmt.Printf("Error opening pin! %s\n", err)
return
}

// turn the led off on exit
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for _ = range c {
fmt.Printf("\nClearing and unexporting the pin.\n")
pin.Clear()
pin.Close()
os.Exit(0)
}
}()

go buttonHandler(pin)

// http listen
http.Handle("/", websocket.Handler(EchoServer))
http.ListenAndServe(":8080", nil)
}

// handle websocket connection
func EchoServer(ws *websocket.Conn) {
w := bufio.NewWriter(ws)
w.WriteString("Hello, i will tell you if button is pressed\n\n")
w.Flush()

for {
<-ctrlChan
w.WriteString("Kachhinggg... somebody pressed the button\n")
w.Flush()
}
}

// check if button is pressed
func buttonHandler(p gpio.Pin) {
for {
if p.Get() {
ctrlChan <- true
}
time.Sleep(150 * time.Millisecond)
}
}

You see there I connect 2 client. One browser and the other one is cli app that I created. Notice that they got their messages alternately between each other. This is because they are sharing the same channel. I will leave it to you my kind reader as an exercise to make it broadcast the message instead of distributing them :)

all source are available at https://github.com/yulrizka/go-pi-experiments


osx-push-to-talk App

March 22, 2015

Push To Talk app for OSX

PushToTalk App
PushToTalk App installer


As a part of scrum teams, every day I need to give updates to my team via Google Hangout. We have a team here in the Netherlands and also in Indonesia. Some times I am in the same room as a colleague of mine. This sometimes quite annoying because I can hear my self (with a delay) from his mic. This somehow messed up my brain. Google Hangout already has a 'auto adjust mic volume' that is really great which cancel the noise. But we still have a problem and end-up muting each other when we want to talk.

There are currently an App that does this already on Apple store, and pretty cheap too. Nevertheless I could not find the one that is suitable for my needs. And I would like to develop an OSX app since I never done it before. Even though i have a hate-love relationship with XCode, I have to give credits to XCode. It's quite easy to create an app like this.

PushToTalk Off state
PushToTalk on State
Status bar indicator

The app sits on status-bar (tray icon ?). By default it muted the microphone and show translucent mic icon. If you hold down the Right Options key, it will un-mute the microphone as long as you pressed it. when you release the key, it will mute the microphone until you press the key again or quit the application.

Everything is at github.com/yulrizka/osx-push-to-talk:

  • DMG Installer
  • Source

I've only tested this app on my MacBook running Yosemite.

If you are on Linux, there is also a phython GTK app that does this really nicely.

If you are on windows, well Godspeed my friend :)

veel succes!

1
</p>


Tracking origin of bugs with git bisect

January 16, 2015

Disect
Disect the rocket, image by ProudloveNathan Proudlove

I've been involved with a iOS project this past week. I'm adding functionalities to the CommonSense iOS library. One of the most annoying thing is that it took about 2 minute to load the project. This is only happened in the unstable branch. The master branch seems to be working fine. So I knew that somewhere there is a commit when this starts happening.

Now this is a good example where git bisect is very useful. It will perform a binary search through commit history until the first bad commit found. So you start with a commit and you marked is as a 'good' or 'bad'. Then every time you mark a commit as good / bad, it will then checkout another commit half way in the middle point between previous history. In each checkout then you test the code and see whether the bugs exist or not.

Here is an example

12
# let's start bisecting, Im in unstable branch,
➜ sense-ios-library git:(unstable) $ git bisect start

the prompt sense-ios-library shows the current folder, and git:(unstable) show current commit. it's part of oh-my-zsh plugin

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
# I open the xcode, and it took quite a long time. so let's marks current revision as bad
➜ sense-ios-library git:(unstable) $ git bisect bad

# I know the master branch don't have this problem, so let's mark it as good
➜ sense-ios-library git:(unstable) $ git bisect good master

Bisecting: 9 revisions left to test after this (roughly 3 steps)
[c1841c0f99a4fa788c14c7437fac7c9547c768c9] Merge pull request #45 from senseobservationsystems/feature-KeepDataLocally

# now I'm in c1841 commit, I tested again with xcode, and found no problem, mark it as good

➜ sense2 git:(c1841c0) $ git bisect good

Bisecting: 4 revisions left to test after this (roughly 2 steps)
[06bbd23c4af8f7008abfb814e1375b271e0b23e9] Update interface and write tests lsit( APPEND CMAKE_CXX_FLAGS "-std=c++0x")

# tested again, it's good
➜ sense2 git:(06bbd23) $ git bisect good

Bisecting: 2 revisions left to test after this (roughly 1 step)
[71517b7923143a8cf1ce205341dd6942c9468198] Added threshold for checking to remove old data from local storage to save battery life

# Tested again, Now I'm beginning to see the problem. Let's mark this bad
➜ sense2 git:(71517b7) $ git bisect bad

Bisecting: 0 revisions left to test after this (roughly 0 steps)
[e5c40d450193ac14fc2faa8c1f4dba2c7c2646f1] Updated functionality and tests of getting local data

# ....
# and we keep doing this until we find the first commit when it was introduced.

# Now let's check our progress using log

➜ sense-ios-library git:(71517b7) $ git bisect log

git bisect start
# bad: [af42213324297e1234767f9224ec1af326514292] Merge pull request #48 from senseobservationsystems/feature-LocalStorageInterface
git bisect bad af42213324297e1234767f9224ec1af326514292
# good: [19f751627d152b89d3f2ecadb144507fcf9293fc] Merge pull request #43 from senseobservationsystems/unstable
git bisect good 19f751627d152b89d3f2ecadb144507fcf9293fc
# good: [c1841c0f99a4fa788c14c7437fac7c9547c768c9] Merge pull request #45 from senseobservationsystems/feature-KeepDataLocally
git bisect good c1841c0f99a4fa788c14c7437fac7c9547c768c9
# good: [06bbd23c4af8f7008abfb814e1375b271e0b23e9] Update interface and write tests lsit( APPEND CMAKE_CXX_FLAGS "-std=c++0x")
git bisect good 06bbd23c4af8f7008abfb814e1375b271e0b23e9

# when you reach the final commit, you will be shown the commit log and modified file

➜ sense2 git:(e5c40d4) $ git bisect bad

e5c40d450193ac14fc2faa8c1f4dba2c7c2646f1 is the first bad commit
commit e5c40d450193ac14fc2faa8c1f4dba2c7c2646f1
Author: Jhon Doe <jhon-doe@sense-os.nl>
Date: Thu Jan 8 14:38:07 2015 +0100

Updated functionality and tests of getting local data

:040000 040000 0a82ee52c68bae4dacc1fec603ce0747b1df426c cd55743c27d2ba7554dfc3d021616b62957c4bba M Sense Library Tests
:040000 040000 8a01944a75e80534124a7a657254e38002518f62 5d14fb11caa352acc7352c85e6a1c08794ae9e65 M SensePlatform.xcodeproj
:040000 040000 a5e3eb78c4c352e7c010b8a4e90c12248f0ec9b0 2174d7ad531a7d989d313c826445434a073b433c M SensePlatformTestAppTests
:040000 040000 4a40764a31981c172a089cd834eb9666b081f3f5 0713beb3c64f1b6f1d2a7811f59be4a82ec30d66 M sense platform

Now that you know when was the bugs introduced. you can now start looking at the problem.

I found out there is something that doesn't feel right here github:commit/e5c40. There is a reference to Xcode.app in one of the folder. So every time I open the project, or switch branch, it will try to look into things inside Xcode.app. So removing the reference indeed solve the problem.

The bisect function is very versatile tool to track down when a bug was introduced. You can even automate the test so you don't have to check each bisect commit your self. The bisect documentation provide a good explanation about the command and also an example on how to automate the test.

Now go on catch and squash those annoying bug!

1
</p>


Stubbing Time.Now() in golang

October 27, 2014

Some time it's really hard to test functionality that involves with system time. Especially when we wanted to test specific functionality. For example testing whether today is end of month. It's unrealistic to run this test case once every month.

If you are coming from ruby land, you might familiar with some test library that solve this problem like timecop. Actually it's not that hard to do it in Go also. There is couple of approach you can use.

First approach is passing the time.Time object to every function.

123
func CheckEndOfMonth(now time.Time) {
...
}

This way you can either pass time.Now() in your main pacakge or call it with something like time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC) in your test. This work well but it's a bit cumbersome to pas it evertime we call the function

Another approach you can use, is to create a function to generate current time. And during the test you can change the implementation of the function. Here is how i do it (and a bonus function to generate begining of month and end of month)

1234567891011121314151617181920212223242526272829303132
package main

import "time"

type nowFuncT func() time.Time

var nowFunc nowFuncT

func init() {
resetClockImplementation()
}

func resetClockImplementation() {
nowFunc = func() time.Time {
return time.Now()
}
}

// function to return current time stamp in UTC
func now() time.Time {
return nowFunc().UTC()
}

// return beginning of month in UTC
func beginningOfMonth(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC)
}

// return end of month in utc
func endOfMonth(t time.Time) time.Time {
return time.Date(t.Year(), t.Month()+1, 1, 0, 0, 0, 0, time.UTC).Add(-1 * time.Nanosecond)
}

now in your test you could do something like this:

123456789
// change implementation of clock in the beginning of the test
nowFunc = func() time.Time {
return time.Date(2000, 12, 15, 17, 8, 00, 0, time.UTC)
}

//...

// after finish with the test, reset the time implementation
resetClockImplementation()

now to the process that, it will see that currently it's 15 December 2000 8:00 UTC

1
</p>


My account just got hacked by Romanian (Possibly)

July 27, 2013

You are probably familiar with above images. Some random friend sent you an email which you can instantly recognize as a spam because it only contains one link. Couple days ago I receive this email which is not the first time for me. But this time it was different. It actually came from my own Yahoo! account which I never use since more that one year ago.

My first instinct is to check whether the mail really got sent from my account or it just spoofing my email address. I kinda guess already that it is using my main account because the list of recipient is looks like it came out of my address book. So I went to my account and check the sent mail folder and there it is. One email message containing a spam that I actually sent to my friends and family.

Did some digging to my authentication history and found out that somebody from Romania has access my account. How could this be. I've never use the account since one or more year ago, I'm an IT guy so I know a little bit about security. I don't click some random suspicious link. I don't install any annoying-spyware-browser-toolbar. The password is 12 character long with apla-numeric and random symbol. Thank god that I don't use the same password for all of my account.

I did again some digging to the given IP address and found out that the IP address came from a location in Rumania. But again this would not be his/her real IP. If i was to send a spam, I will route my email through bunch of proxy all over the world to cover my track. Or probably they don't even bother because they just using it for spam.

Interesting part is I stumble upon this article saying about Romania has became a Global Hub for hackers and online crooks. According to the article that it's became a commonplace for some hacker to harness people personal information and use it for illegal activity.

Luckily I don't store any sensitive information on my email. It would have some serious impact if I store password or bank account information.

Also something that I notice is most of this spam email came from my friends account which also uses Yahoo! mail. Or probably I just never notice.

What can you do when this happened to you

If you ever received / sent this email. I would suggest you to:

  1. Tell the person to reset their account password
  2. Don't store or send sensitive information unencrypted with email like: password, keys, bank account info
  3. If you need to send sensitive information, try encrypting it first. I go into details of doing that in Safely sharing credentials with PGP. I'm start doing this from now on.
  4. Use some secure password, and don't use the same password for all of your account.
  5. If you can, try to change the password on a regular basis. or use service like LastPass
  6. When this is your work email that sometimes contain private information. Use service that offer two factor authentication like gmail does you need to enable it.
  7. Stay safe friends, internet is a dangerous place
1
</p>


berks upload core dump

July 21, 2013

Berksfhel is cookbook dependency for chef. If you are familiar with ruby / python, think of it as a Bundler or virtual environment for chef

I faced this core dump error while doing berks upload. That command will actualy push some cookbook to a chef server.

123456789101112131415
$ berks upload
/home/user/.rbenv/versions/1.9.3-p362/lib/ruby/gems/1.9.1/gems/celluloid-0.14.1/lib/celluloid/tasks.rb:47: [BUG] Segmentation fault
ruby 1.9.3p362 (2012-12-25 revision 38607) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0004 p:0112 s:0009 b:0007 l:002040 d:000006 BLOCK /home/user/.rbenv/versions/1.9.3-p362/lib/ruby/gems/1.9.1/gems/celluloid-0.14.1/lib/celluloid/tasks.rb:47
c:0003 p:0031 s:0005 b:0005 l:002108 d:000004 BLOCK /home/user/.rbenv/versions/1.9.3-p362/lib/ruby/gems/1.9.1/gems/celluloid-0.14.1/lib/celluloid/tasks/task_fiber.rb:11
c:0002 p:---- s:0003 b:0003 l:000002 d:000002 FINISH
c:0001 p:---- s:0001 b:-001 l:000000 d:000000 ------

-- Ruby level backtrace information ----------------------------------------
/home/user/.rbenv/versions/1.9.3-p362/lib/ruby/gems/1.9.1/gems/celluloid-0.14.1/lib/celluloid/tasks/task_fiber.rb:11:in `block in create'
/home/user/.rbenv/versions/1.9.3-p362/lib/ruby/gems/1.9.1/gems/celluloid-0.14.1/lib/celluloid/tasks.rb:47:in `block in initialize'

....

upgrading the ruby verison to 2.0 seems to resolve my issue.

1
</p>


Safely sharing credentials with PGP

July 8, 2013

When working in teams, we are sometimes required to share some password / keys with our team. The most common way for me is probably through email or some chat client. But even though its convenience it's not actually a secure and a good practice. Especially if you are providing a service that deal with sensitive information.

Some simple approach would we communicating the password directly with a person through secure medium. One way to do it is both party ssh through a server and use talk client like write. But for some cases it's quite impractical.

PGP

Enter PGP. It's basically a software that do a Public-key cryptography. Public-key cryptography is basically encryption process which require 2 keys, one for encrypting and the other one for decrypting. Usually the public key is used for encrypting and private key is use for decrypting. I would not dive into the details about it since I've only have basic understanding about it. But for those people that is interested, you would read the nice article on wikipedia

There is a open source project called GPG (GNU Privacy Guard) and in this article I would like to show you how we could share some password / key file with it.

Instalation

If you don't already have it on your system, you could installed it with:

1
$ sudo apt-get install gpg

After installing we would start by creating a pair of keys bash $ gpg --gen-key

You will be asked with bunch of questions. Most of the answer you could leave it as a default but most important is fill in your email address and also provide a Passphrase to protect your key with password. When it finish gathering information, it will start creating a key pair by using system entropy. You can help the system to generate the entropy by clicking or moving your mouse randomly or doing some random IO disk by triggering for example find /

Listing keys

After installing, you can see list of keys by using this command

123456
$ gpg --list-keys
/home/user/.gnupg/pubring.gpg
--------------------------------
pub 2048R/70280895 2013-07-09
uid Ahmy Yulrizka (ahmy135@mail.com) <ahmy135@mail.com>
sub 2048R/F7B2D44C 2013-07-09

In above output you could see that we have created public key with id of 70280895. Note this one because we are going to use it later when submitting the key to a key server

Exporting keys

To share your public key, so other people could send you encrypted message.

Note that further in this article I will discus ways to easily distribute your public key.

12345678910
$ gpg --armor --export 'ahmy135@mail.com'
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (GNU/Linux)

mQENBFHcRTEBCAC056qG97iJAtb604x5Hr+3lIi3UXVOnGauoHSo5S8S3bSCD0Ib
DzgSjWj8a6Xd1BY+5+HV0amp+i1sTknnd/C2WR7O1h9DIasPlWktPr2T+j4IGnYF
...
-----END PGP PUBLIC KEY BLOCK-----

$ gpg --armor --export 'ahmy135@mail.com' --output pubkey.txt # to output it to a file

Encrypting and decrypting

With those generated keys, we could now do a personal encryption. That is if you want to encrypt a file and you are the only one who are able to decrypt it.

12
$ echo "this message is secret" > message.txt
$ gpg --encrypt --recipient 'ahmy135@gmail.com' message.txt

Those code will create a file name message.txt.gpg which is encrypted message of message.txt

12345678910
$ gpg --decrypt message.txt.gpg

You need a passphrase to unlock the secret key for
user: "Ahmy Yulrizka (ahmy135@mail.com) <ahmy135@mail.com>"
2048-bit RSA key, ID F7B2D44C, created 2013-07-09 (main key ID 70280895)

gpg: gpg-agent is not available in this session
gpg: encrypted with 2048-bit RSA key, ID F7B2D44C, created 2013-07-09
"Ahmy Yulrizka (ahmy135@mail.com) <ahmy135@mail.com>"
this message is secret

As you can see that we are successfully decrypted the message. This example you encrypt the message using your own public key. So this method only work if you want to archive or backup the file securely. In order to send someone else an encrypted message, you need to encrypt the message using the other person public key

Distributing the key

In order for any body to send you a encrypted message, you need to give your public key. Since public key only used for encryption, It's OK to publicly share your public key. But never share your private key. Once the other party have your public key they could start send you an encrypted message using the command above.

You could share your public key manually to some one (through usb / email etc) by exporting it first just like I mention before. But there are an easy way to distribute the key. There are some public GPG server that store your public key so that other people could easily find it and import it into their local machine. There are http://pgp.mit.edu and also ubuntu key server http://keyserver.ubuntu.com that we can use.

To send our key to MIT server we could do

12
$ gpg --send-key --keyserver pgp.mit.edu 70280895
gpg: sending key 70280895 to hkp server pgp.mit.edu

the last number 70280895 was the key id of the public file. You could find it with the output of gpg --list-keys command. Now we have successfully send our public key any body could get your public key through that keyserver. You could test this by searching a name or email or a person in the key server web interface. for example try searching my name on http://pgp.mit.edu/

Importing Keys

Now to import other people public key, we could also do that in two way.

if the person give you a file which contain their public key (say ahmy-pub.key). you could import it with

1
$ gpg --import ahmy-pub.key

Or if the person already publish his public key to a keyserver, we can search it with

1234
$ gpg --search-keys 'Ahmy Yulrizka'

# or
$ gpg --search-keys 'ahmy135@mail.com'

It will generate a list of keys that found on the keyserver. Enter the number of the keys and it will be imported to your local machine.

after importing you can send an encrypted message to the person for example

1
$ echo "This is also a secret" | gpg --encrypt --armor --recipient 'Ahmy Yulrizka' > output.txt.gpg

You could provide a name or an email address as a recipient. THis command will encrypt the message using public key of a person name Ahmy Yulrizka

Conclusion

At this point you are able to generate, export, distribute and import keys. More over you can already encrypt and decrypt file / message to a designated recipient. The the part two of this article I will share some idea how we could share some password / password key to other member of the team.

1
</p>


Homeward light indicator with RaspberryPi and CommonSense

February 26, 2013


I've been tinkering with my [raspberry-pi][raspberry-pi] for quite some time now. What I like about it because it is cheap ($25), it's run Linux (especially debian based) and most of all it's have General Purpose Input Output pin. Since I was a kid, I always wanted to control electronic appliance remotely. Luckily my friend [@pimnijdam][pimnijdam] thought me how to control a relay board. Basically it's just like an electric switch that connect/disconnect current when you supply a low voltage.

So I connect one of the GPIO pin to the relay board and from the relay board to the lamp. Now I can control the desk lamp through my raspberry-pi by issuing a linux command. Had been successfully doing this, I wanted to the lamp not only from the raspberry pi but anywhere. The easiest way that I could think of is running a web server inside the raspberry-pi. The debian repository is quite awesome. So I could install a ruby/python and it only took a single command.

So I did create a [project][pi-sinatra-github] with ruby/sinatra to control this light. Its really small (30 lines of code, 80 lines html + js) and with this project I can control up to 3 light, one of those eventually control the light. In case you are interested, I put the source on [github][pi-sinatra-github]. This project uses [pi-piper][pi-piper] a ruby library that wrap [wiringPi][wiringPi], which is library that is used to control the GPIO pin.

homeward indicator
The light will turn on whenever I leave the office at noon.


lamp off
Controlling Lamp with Raspberry-pi + ruby/sinatra
1
</div>

The phone open a web browser to the raspberry pi

Now, turning a desk lamp with pi is something; But it's quite boring and not really useful. Now let us make something a bit interesting. Instead of controlling it manually, The light be trigger on my activity. In this case I the light to turn on when ever I came back from the office on every working day. So at home my wife know exactly when I leave the office. I already have it running a web server, so basically I can control it from my mobile phone. But I don't want to do this every single day. And this is where ComonSense really makes thing easy for me.

CommonSense is a platform to store, retrieve, analyze and interpret our sensory data. What is a sensor ? well anything could be a sensor. From physical sensor on our mobile phone like accelerometer, noise, position, cell network, light, ambience and more sophisticated sensor like sensor that tell your quality of sleep. By using one or more sensor, it could create more intelligent sensor. For example a sensor that tell wether you are standing or sitting by analyzing the accelerometer data. CommonSense is Awesome!, but for this experiment we will be using a simple location sensor. It will tell where is my current location by GPS or wifi-network.

What is make it easy is I don't have to create an application on my mobile phone. CommonSense already have a platform that run on Android or iOs. The application act as an agent that collect and sample sensor data from the mobile phone. By it self it's not really doing much right now but combine with the CommonSense make it really easy for a developer like me to easily experiment with my data. So with this sense app, the raspberry-pi could easily get data from my mobile phone through the CommonSense API.

sense app
Sense Android App - Works as an aggent of CommonSense
1
</div>

biking out of the office
The light will turn on when I'm 200m away from the office

Again, my awesome colleague @pim create a prototype of python framework that make it very easy for me to implement my project. You should definitely chek it out!. I've created the homeward light indicator project using the early version of the framework. This is actually my first encounter with Python. Although I still prefer doing my project with Ruby, I'm really enjoying working with Python.


Responsive Design

February 24, 2012

I've been playing around with twitter bootstrap. It's like a css framework to help designer or developer create a nice and clean site. It's offer grid system, predefine layout, button, javascript, carousel etc. You can build website in just a few hours. Very nice for prototyping.

I've been using it to build this blog since it was version 1. Recently i had a chance to upgrade it to version 2. The new version offer a lot of functionalities, one the feature that I play a lot is the responsive design.

Basically Responsive Web Design (RWD) means the ability of the web site to adapt to the user screen size. So the page should look different in a way that it suited for specific screen. Like this website will look different if it's open with mobile phone, portrait mode on tablet, landscape mode on tablet, net book or even in a large desktop. This actually achieved by using W3C CSS3 media query. It means that it uses different stylesheet for each of the screen size. More info on RWD in twitter bootstrap can be found here

You can test this functionality by resizing your browser window. Try to drag it slowly and watch the page banner slightly change. here are the screen shoot of the design.

  • Desktop View
    Desktop View (1210px and up)
  • Tablet Landscape
    Tablet Landscape (768px to 979px)
  • Tablet View
    Tablet Portrait (480px to 768px)
  • Tablet with menu
    Tablet Portrait with menu (480px to 768px)
  • Mobile Phone
    Mobile Phone (480px and below)
  • Mobile Phone with menu
    Mobile Phone with Menu(480px and below)


Jekyll error utf-8 caracter

January 14, 2012

If you having a problem in jekyll when it didn't generate a post and there is no error in the log file. you might want to check the content if there is any UTF-8 character encoding such as this ±

The problem arise if you use ruby 1.9. It rejecting a file that contain non-ASCII character. it actually got invalid multibyte char (US-ASCII) error message

to solve this. I added this line to .bashrc or zshrc if you are using zsh

12
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

It should fix the problem now.


Testing ruby code with benchmark_suite

January 14, 2012

Just a couple days ago I found out therubygame.com which challenge us to solve a problem with ruby. The result were measured by the fastest, slowest, shortest, longest, cheaters (yup there are also some rule).

And also I was listening to an episode of ruby rouge on Benchmarking. And there is one tools called benchmark_suite.

So there is this challenge to capitalize first letter of every word. I want to compare my code to the fastest solution there. so i installed the gem, also the ruby-ffi gem that somewhat fix an error while I tried to run the benchmark.

so this is the code to benchmark it

12345678910111213
require 'benchmark/ips'

string = "The small brown & ginger fox JUMPED OVER the gate"

Benchmark.ips do |x|
x.report("first") do
string.gsub(/\w+/){|w| w.capitalize}
end

x.report("second") do
string.split.map(&:capitalize).join ' '
end
end

And here are the result

first 55609.3 (±10.7%) i/s - 277202 in 5.048175s (cycle=4471)

second 77996.4 (±10.2%) i/s - 389844 in 5.055319s (cycle=6188)

The first code run 55.609,3 times per second and the latter is 77.996,4 times per second. So the second code run more than the first code in one second. Which mean the second code is faster.

Also the first code run 277.202 times in 5.048175 sec while the second code run 389.844 times in 5.05 sec

So this mean, that regex is more slower then calling capitalized on each element on array

1
</p>


Archives

    2015

  • Aug Testing go 1.5 cross compilation on raspberry pi
  • May Telepon murah ke Indonesia dengan voip
  • Mar osx-push-to-talk App
  • Jan Tracking origin of bugs with git bisect
  • 2014

  • Oct Stubbing Time.Now() in golang
  • 2013

  • Jul My account just got hacked by Romanian (Possibly)
  • Jul berks upload core dump
  • Jul Safely sharing credentials with PGP
  • Feb Homeward light indicator with RaspberryPi and CommonSense
  • 2012

  • Mar Scale MongoDB dengan Sharding
  • Feb Ruby Fiber apaan sih ?
  • Feb Responsive Design
  • Jan Jekyll error utf-8 caracter
  • Jan Testing ruby code with benchmark_suite

Let each man exercise the art he knows

Welcome to my canvas. A place for me to explore and experiment on some stuff that I found interesting.

Ruby (and Rails)

Ruby is a neat language. People create clean, elegant and smart app with it. Rails is web framework built on top of ruby. In this category I will explore stuff related to ruby and also rails

Web

This is general category involving various aspect of web technology. I like to explore not only the programming and technology aspect of the web, but also the design

Labs.Yulrizka.com
    • Left Panel
    • No Panel
    • Right Panel
twitter github feed
  • Home
  • Ruby (and Rails)
  • Web

© Ahmy Yulrizka 2012. This site is made with Jekyll using Twitter Bootstrap and hosted on Github pages. All of the content is open and the source can be accessed here