Carpe diem (Felix's blog)

I am a happy developer

Earthquake Early Warning Prototype

I made a prototype of earthquake early warning system in one week. The scenario goes as follows: We use a Friendly ARM SBC (Single-Board Computer) as an earthquake signal collector and processor. If the signal was identified as serious earthquake, it would send a message to our server. Then our server will authenticate the message and use Apple Push Notification Service (APNS) to notify some iPhone registered for the notifications.

The demo video:

Apple Push Notification Service (APNS)

There are two ways to show up a notification even if app wasn’t active. One is local notification and the other is server-pushed notification.

Local notification are scheduled by an iOS application. It’s iOS only.

Push notification are sent by a remote server to Apple Push Notification service, which pushes the notification to devices on which the application is installed.

There are a lot of limitation in alert message. So one must use it wisely. The maximum size allowed for a notification payload is 256 bytes. APNS refuses any notification that exceeds this limit. The notification is encoded in a JSON string, the properties go as follows:

  • alert If this property is included, iOS display a standard alert. This property can be a string or a dictionary. If it was a dictionary, below are the properties of alert.
    • body The text of the alert message
    • action-loc-key Display an alert with two buttons. The right buttons’s title would be this key.
    • loc-key A key to an alert-message string in a Localizable.strings file for the current localization.
    • loc-args Variable string to appear in place of format specifiers in loc-key.
    • launch-image The file name of an image in application bundle, which will be shown on the display message.
  • badge The number to display as the badge of the application icon.
  • sound The name of the sound in the application bundle. Set the property to default then the default sound is played.

To develop and deploy the provider side of a client/server application, you must get SSL certificatates from Apple Dev Center. Apple has a guide for this.

After setting up provisioning on Dev Center, you can get the certificate and key in .pem format, with following commands.

openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12

Remember to setup your bundle identifier and code sign as same as your provisioning profile uploaded to apple.

Sometimes you might bump into bugs that your code sign wouldn’t work when you renew your bundle identifier. If so, just restart XCode.

Server CGI script

I use Perl to be cgi server. There are already a lot of APNS plugins that you can find in most popular languages. So just pick what is comfortable to you for implementing server side application.

My script that handles APNS looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env perl
use Net::APNS;

my $apns = Net::APNS->new;
my $notifier = $apns->notify({
  cert => "cert.pem",
  key => "key.pem",
  passwd => "passwd",
});

$notifier->devicetoken("202154bb3b92e71f02b011183dfc7ad1261b69007346b52d1c8bcdb5aef9f4dd");
$notifier->message("Earthquake!!");
$notifier->badge(1);
$notifier->sound('default');
$notifier->sandbox(1);
$notifier->write;

The device token is generated by your app. You will first register when your app launch, then get the token from method - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@implementation FCAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
        (UIRemoteNotificationTypeAlert|
         UIRemoteNotificationTypeBadge|
         UIRemoteNotificationTypeSound)];
    // Override point for customization after application launch.
    return YES;
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"My token is %@", deviceToken);
}
@end

ARM board

I use Friendly ARM 6410 for prototyping.

mini6410

Here are some configuration details:

booting

In minicom remote shell:

> boot-args:
> root=/dev/mtdblock2 rootfstype=yaffs2 init=/linuxrc console=ttySAC0,115200

The boot args is quite important else you won’t get the shell from the device or you may not boot it successfully. It took me a while to find the correct boot args.

cross compile

If some desired library are not included in the board, you can cross compile it from source. However, the configuration is a bit complex then normal compilation:

$ ./configure --host=arm-linux-gnu --target=arm-linux CC=arm-linux-gcc \
$ AR=arm-linux-ar LD=arm-linux-ld RANLIB=arm-linux-ranlib \
$ --prefix=/opt/curl --without-ssl

The cross compiled library can be uploaded to ARM board via ftp:

$ ncftp -u user -p passwd $IP
> put curl.tar.gz

You can find the $IP in minicom remote shell by ifconfig.

Comments