Inspirated

 
 

April 11, 2010

Workaround for getting received SMS’ sender number in PyS60

Filed under: Blog — krkhan @ 9:22 pm

It’s fairly simple in PyS60 to get the sender’s details whenever a new SMS is received. However, if the sender has an entry in your address book these details translate to just the contact name. That way, if the contact has multiple numbers you have no idea which number was used to send the text. Here’s an ugly little workaround for this issue:

received-sms-number.py

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def message_received(id, box):
    box.sms_messages()
    sender = box.address(id)
 
    if sender[0] != '+' or sender[1:].isdigit() == False:
        # Try to find the sender's number from log.
        logged_sms = logs.sms(mode = 'in')[0]
 
        # To confirm that the log entry is the same one we're concerned
        # about, do some checks.
        if logged_sms['subject'] == sms_text[:64]:
            number = logged_sms['number']
            contacts_db = contacts.open()
            found_contact = contacts_db.find(number)
            if found_contact:
                title_match = True
                for token in sender.split():
                    if found_contact[0].title.find(token) == -1:
                        title_match = False
                if title_match:
                    sender = number
 
    print "SMS Received from: ", sender

You can use this little snippet of code to reply back to the sender even when there’s a matching entry in the contacts database. This in turn opens up a whole new range of interesting ideas for auto-responding applications.

Tags: , , , , , ,

April 1, 2010

71 days of E71: Top 10 3rd party applications

Filed under: Blog — krkhan @ 2:05 pm

While I would have sold my clothes, PS2 as well as my soul to get my hands on a N900, I couldn’t strike a practical deal and in the end had to settle for E71. Now, while E71 does not ooze sex by running a full-fledged Linux distro it still does a pretty good job of running Symbian. The specs are fun, the keypad is great and the build quality is nothing but ergonomic love.

After completing 71 days of tinkering with the new phone, I have settled on the choice of apps which would become an integral part of my digital life. I’m listing the top ten here, but the arrangement is in no way meant to be indicative as an absolute index of application quality. These are just the ones that I found useful.

10. ScreenSnap — Honorary Mention

It would be a bit unfair to not list the very application that powers the visual aspects of this post. So here we are with the self-referential snap:

ScreenSnap Screenshot

9. SmsOne — Hassle-Free Flash SMS

“Flash” texts — the ones which always instantly show up on the recipient’s cell and are not saved in the inbox unless specifically made to — have always been a speciality of applications with poor interfaces as well as poorer integration with the rest of the phone. SmsOne, on the other hand, has a simple interface with excellent phonebook integration for making the job as simple as possible.

SmsOne Screenshot

8. Mobipocket MobiReader — eBooks Made Fun

Reading a large PDF file on your E71 is indeed possible, but it takes away any fun whatsoever by forcing you to deal with redundant scrolling and weird font sizes. MobiReader combined with the desktop software Calibre is the ultimate eBook reading experience on Symbian phones.

MobiReader Screenshot

7. Gravity — Pulling Tweets Consistently

The one word for summarizing Gravity would be: slick. Of all the Twitter applications for Symbian — and there are quite a lot — Gravity is the most organized, reliable and pretty-looking competitor around.

Gravity Screenshot

6. PuTTY — That Insane Power in Your Hands

I’m lying down in my bedroom and I want to play this song on the speakers in my drawing room. I’m in my university and I want to start this download on my laptop which is unfortunately back at home. I’m in another city and I want to see the contents of this file which is in my home PC.

I can. Because I have that command-line access at my fingertips:

SmsOne Screenshot

5. mIRGGI — IRC Never Dies

Open-source — being the distributive collaboration that it is — depends heavily on mailing lists and IRC channels for communication. For the latter, mIRGGI works flawlessly. In fact, you can even do fancy stuff like using different network connections for different channels.

mIRGGI Screenshot

4. Python — “It’s …”

For all the comparisons made over the years between Perl and line-noise, Symbian C++ easily beats both by a mile. Which is why your choices are rather limited if you want to program for Nokia phones while preserving your sanity at the same time. Your best bet is to go for Maemo. Unfortunately, that ain’t exactly an affordable option for everyone. The other way is to use PyS60 rely on that programming language which makes every other alternative pine for the fjords.

PyS60 Screenshot

3. MSDict Viewer — Dictionaries which Help

A dictionary is one of the least useful things you can carry around. Even with one of them installed on your phone, they rarely get used. Similarly, the pronunciation guides used in those dictionaries are cryptic symbols at best. Add the ability of audio pronunciations and you suddenly have a lovely app referring which almost becomes an addiction.

MSDict Viewer Screenshot

2. Google Maps — Never Lose Yourself

For people who’re not especially good with directions, there couldn’t have ever been a better solution:

Google Maps Screenshot

1. Opera Mobile — Synonym for Excellence

Even if this list is tailored more to my requirement, get some hundred people to make similar ones and Opera will be the topper in majority of the rankings. Opera bridges that gap between mobile browsing and real browsing and is one of those applications which epitomize how software should be engineered.

Opera Mobile Screenshot

Tags: , , , , , , , , , , , , , , , ,

February 7, 2010

Faking User-Agent with PyS60

Filed under: Blog — krkhan @ 12:00 am

“Anyone who slaps a ‘this page is best viewed with Browser X’ label on a Web page appears to be yearning for the bad old days, before the Web, when you had very little chance of reading a document written on another computer, another word processor, or another network.” — Tim Berners-Lee in Technology Review, July 1996

People never learn. Slapping such labels is one thing, they even go as far as adopting brain-dead practices of checking user-agent strings and refusing service to any browser not originating from Redmond. For example, Opera Mobile — the sexiest mobile application on planet — works astonishingly well for Javascript websites. Nevertheless, when trying to browse my university’s academic management portal on it I am presented with a big ugly “We’re dumb, you need to open this page with Internet Explorer 6.0 or later because it uses JAVASCRIPTXX0RZ.” Even though Opera does allow spoofing of user-agent strings, the fake strings still contained “Symbian” as the operating system which still resulted in incompatibility errors.

As ever, Python came to the rescue. Firing up the Twisted framework, I created a simple HTTP proxy which modifies the user-agent string on the fly. Peaches:

Opera Mobile User Agent Spoofed
User-Agent Proxy Screeshot

The script is still very quirky and is the farthest thing from what you’d call a stable solution. You can download the inital release here. The zip file contains the tiny proxy server script as well as Twisted and Zope dependencies. Good luck with trying to counter retards who’re doing everything they can to avoid compatibility. Yes, even 14 years after Sir Tim’s veracious proclamation.

Tags: , , , , , , , , , , ,

February 6, 2010

Inbox Stats v1.1 — S60 3rd Edition Compatibility

Filed under: Blog — krkhan @ 3:16 pm

Continuing the migration to E71, here’s the new release for Inbox Stats which works on Python 2.5 releases:

inboxstats-1.1.zip
Inbox Stats v1.1 Screenshot

Tags: , , , , , , , , , , , ,

CSV Auto-Responder v1.0 — S60 3rd Edition Compatibility

Filed under: Blog — krkhan @ 3:16 pm

As I finally got my hands on a S60 3rd Edition device last week in form of E71, it was obviously the time to fix my PyS60 scripts for the new version. By using some workarounds to fix some brain-dead compatibility issues which I will detail in a later post, I was able to get CSV Auto-Responder running properly:

csvautoresponder-1.0.zip
CSV Auto-Responder v1.0 Screenshot

Tags: , , , , , , , , ,

November 21, 2009

PyS60 CSV Auto-Responder v0.1

Filed under: Blog — krkhan @ 8:11 pm

The idea is pretty simple actually. You run the application on your cellphone and give it the path of a CSV file. The file contains some data which can be queried. For example, let’s assume that the contents are:

ID,Name,Age,Message
0,The Black Knight,43,”I move for no man”
43,Sir Galahad, 38,”Oh, let me have just a little bit of peril?”
569,John Doe,21,”Hello World”

Next, you choose a keyword; something simple like “Respond”. Then, you put the cellphone aside. It keeps checking the incoming SMS messages and as soon as it receives a message having something similar to … :

Respond 43

… it queries the CSV file and replies to the sender with results of the lookup. In our case, the reply will be:

Received query 43 from +xxxxxxxxxxxx
Found record in database:
> Name: Galahad
> Age: 38
> Message: Oh, let me have just a little bit of peril?

And that is it. The script can be downloaded from this link. Updates in future shall be linked on its specific Inspirated Code page. Here’s the whole thing in action:

PyS60 CSV Auto-Responder

Tags: , , , , , , , , ,

October 31, 2009

HOWTO: Use PyS60′s Bluetooth Console on Fedora/Ubuntu/Debian Linux

Filed under: Blog — krkhan @ 11:03 pm

While developing PyS60 apps is one of the most fun things you could do with your Nokia phone, debugging them isn’t as zippy as one would hope for in a Py development environment. To make up for that, PyS60 gives the developers an option for directly connecting to the interpreter through Bluetooth. Doesn’t sound very appealing? How about this: You connect your laptop with the cellphone, jump in at some place in the code while your app is executing and then use lappy’s big keyboard for exploiting different code and values in the interpreter. Sounds better?

To accomplish this on a Linux distro, you will need the following packages installed on your system:

Name Links
gnome-bluetooth
uucp/cu

After making sure that both are present on your system, install PyS60 on your phone if you haven’t already done so.

Now the fun part:

  1. Switch on Bluetooth in the cellphone.

    PyS60 Bluetooth HOWTO, Mobile screenshot #1

  2. Launch bluetooth-properties and click on “Setup New Device”.

    PyS60 Bluetooth HOWTO, PC screenshot #1

  3. Select your cellphone.

    PyS60 Bluetooth HOWTO, PC screenshot #2

  4. You will be shown a pin.

    PyS60 Bluetooth HOWTO, PC screenshot #3

  5. Enter the pin when queried on the cellphone.

    PyS60 Bluetooth HOWTO, Mobile screenshot #2

  6. The phone should be successfully paired.

    PyS60 Bluetooth HOWTO, PC screenshot #4

  7. Authorize your Linux system to make automatic connections to the phone.

    PyS60 Bluetooth HOWTO, Mobile screenshot #3

  8. As root, run this shell script:
    [root@orthanc ~]# ./rfcomm-listen.sh

    Serial Port service registered
    Waiting for connection on channel 2

  9. Launch PyS60 interpreter and select “Bluetooth Console” from the application menu.

    PyS60 Bluetooth HOWTO, Mobile screenshot #4

  10. Select your Linux machine.

    PyS60 Bluetooth HOWTO, Mobile screenshot #5

    The command you ran in previous step should have new output:

    [root@orthanc ~]# ./rfcomm-listen.sh

    Serial Port service registered
    Waiting for connection on channel 2
    Connection from 00:17:4B:B6:35:31 to /dev/rfcomm0
    Press CTRL-C for hangup

    The cellphone screen should be showing something like this:

    PyS60 Bluetooth HOWTO, Mobile screenshot #6

  11. As root again, open a new terminal and run:
    [root@orthanc ~]# cu -l /dev/rfcomm0

    Connected.

  12. Hit Enter till prompt (>>>) appears, then type:

    >>> import appuifw
    >>> appuifw.query(u'Hello World', 'text')

  13. Viola, you should have an input box on the mobile screen:

    PyS60 Bluetooth HOWTO, Mobile screenshot #7

  14. Enter any text and press the OK key. It should be show up in the terminal you were using to type in code:

    >>> import appuifw
    >>> appuifw.query(u'Hello World', 'text')
    u’Finally’

  15. Exit the interpreter by typing CTRL+D on an empty line:

    >>> import appuifw
    >>> appuifw.query(u'Hello World', 'text')
    u’Finally’
    >>>
    Interactive interpreter finished.
    cu: Got hangup signal

    Disconnected.

Pat yourself on the back. Now, you can use your Bluetooth console to import your modules, execute some stuff and then jump in the middle to test some extra lines or values. In fact, I found it to be a pretty darned good way of learning about PyS60′s API. Res secundae!

Tags: , , , , , , , , , , , , , , , ,

May 17, 2009

Inbox Stats v1.0 — Because graphs speak louder than numbers

Filed under: Blog — krkhan @ 4:00 am

Inbox Stats v1.0

Changelog:

  • As can be seen from the screenshot above, graphs can be turned on through the options menu. Implementing them resulted in two useful modules:
    • scrolledcanvas: Provides a derived Canvas class which has built-in support for scrolling oversizes images.
    • roundedrectangle: Provides functions for drawing rectangles with rounded corners on a Canvas or Image. Optionally, text can be given which will be prettily centered (and truncated upon requirement) in the drawn shapes.
  • More minor code enhancements and bugfixes.

You can find both the modules and the application itself here. All code is released under the PSF license so feel free to use it any way you want. Oh, and if you still haven’t figured out why anyone would be interested in the SMS stats in the first place, here’s a little quote for you:

“Statistics are like a bikini. What they reveal is suggestive, but what they conceal is vital.”

Tags: , , , , , , , , , , , ,

May 12, 2009

SMS Inbox statistics for Series 60 mobile phones v0.2

Filed under: Blog — krkhan @ 7:04 pm

Update: New version

Improvements in the new version:

  • Previous version hung up while calculating the statistics. The new version dispatches a thread for the dirty work and keeps the user interface responsive with a “Processing” notification.
  • Contact stats are sorted in descending order by the number of messages per each contact.
  • Code improvements for making it more “Pythonic”.

inboxstats.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# -*- coding: utf-8 -*-
"""Script for printing trivial statistics about inbox, such as:
	Number of texts
	Number of unique contacts who sent the texts
	Number of texts sent by respective contacts
"""
 
__author__ = "Kamran Riaz Khan"
__email__ = "krkhan@inspirated.com"
__version__ = "0.2"
__copyright__ = "Copyright (c) 2009 Kamran Riaz Khan"
__license__ = "Python"
__status__ = "Production"
 
import appuifw, e32, inbox, thread
 
def exit_key_handler():
	"Release app_lock."
	app_lock.signal()
 
def parse_inbox_stats(stats):
	"""Parse the inbox statistics,
	Updates the stats dictionary with:
		sms-count : Number of texts
		sms-contacts: List of tuples with following pairs:
			Name of contact, Number of corresponding
			(ordered according to decreasing number of texts)"""
	curr_inbox = inbox.Inbox()
	messages = curr_inbox.sms_messages()
	contacts = {}
 
	for i in messages:
		address = curr_inbox.address(i)
		if contacts.has_key(address):
			contacts[address] = contacts[address] + 1
		else:
			contacts[address] = 1
 
	contacts = contacts.items()
	contacts.sort(lambda x, y: cmp(x[1], y[1]))
	contacts.reverse()
 
	stats["sms-count"] = len(messages)
	stats["sms-contacts"] = contacts
 
def print_inbox_stats(content, stats):
	"""Print inbox stats in the content Text field,
	Remembers the cursor position of Text before the call
	and points at it again after updating the content."""
	pos = content.get_pos()
 
	statsmap = [
		(u"SMS Count", unicode(stats["sms-count"])),
		(u"Unique Contacts", unicode(len(stats["sms-contacts"]))),
		(u"", u"")
		]
 
	statsmap += [(k, unicode(v)) for k, v in stats["sms-contacts"]]
 
	for i in statsmap:
		content.style = appuifw.STYLE_BOLD
		content.add(i[0] + (i[0] and u": " or u""))
		content.style = 0
		content.add(i[1] + u"n")
 
	content.set_pos(pos)
 
if __name__ == "__main__":
	content = appuifw.Text()
	appuifw.app.title = u'Inbox Stats'
	appuifw.app.body = content
	appuifw.app.exit_key_handler = exit_key_handler
 
	stats = {}
	t = thread.start_new_thread(parse_inbox_stats, (stats,))
 
	content.style = appuifw.STYLE_ITALIC
	content.add(u"Processing text messages...n")
	thread.ao_waittid(t)
	content.add(u"Done!nn")
	content.style = 0
 
	print_inbox_stats(content, stats)
 
	app_lock = e32.Ao_lock()
	app_lock.wait()

Inbox Stats v0.2 Screenshot

Tags: , , , , , , , , , , ,

May 10, 2009

SMS Inbox statistics for Series 60 mobile phones

Filed under: Blog — krkhan @ 8:03 pm

Update: New version

Self-indulgence is what I do best. It usually results in me trying to figure out random statistics about my personal life; e.g., graphs about which hours of day I’m mostly awake on and pie-charts about my bathroom habits. Such stuff doesn’t only make me feel more important than I actually am, but also polishes my fundamental math skills which were lost while trying to calculate average number of viruses a Windows user is hit by on an yearly basis.

Texting is what I do second best. Combine the two of my most productive practices and the need emerges of having a way to produce useless statistics about my cell phone’s inbox. This is where PyS60 comes to the rescue. In my previous post I praised Python’s sex appeal. Here’s the demonstration:

  • Total time spent with Python: Less than a week
  • Total time spent with PyS60: Less than a minute
  • Total time spent with Symbian development: Less than never

And still, even a total n00b like me could easily accomplish what he wanted to, using only the library reference manual and 70 lines of understandable code:

inboxstats.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""Script for printing trivial statistics about inbox, such as:
	Number of texts
	Number of unique contacts who sent the texts
	Number of texts sent by respective contacts
"""
 
__author__ = "Kamran Riaz Khan <krkhan@inspirated.com>"
__version__ = "$Revision: 0.1 $"
__date__ = "$Date: 2009/05/10 15:30:00 $"
__copyright__ = "Copyright (c) 2009 Kamran Riaz Khan"
__license__ = "Python"
 
import appuifw
import e32
import inbox
 
def exit_key_handler():
	"Release app_lock."
	app_lock.signal()
 
def inbox_stats():
	"""Parse the inbox statistics,
	Returns the dictionary:
		sms-count : Number of texts
		sms-contacts: Dictionary with the pairs:
			contact-name : Number of texts from contact"""
	cur_inbox = inbox.Inbox()
	messages = cur_inbox.sms_messages()
	contacts = {}
 
	for i in messages:
		address = cur_inbox.address(i)
		if contacts.has_key(address):
			contacts[address] = contacts[address] + 1
		else:
			contacts[address] = 1
 
	return {
		"sms-count" :  len(messages),
		"sms-contacts" :  contacts
		}
 
if __name__ == "__main__":
	content = appuifw.Text()
	appuifw.app.title = u'Inbox Stats'
	appuifw.app.body = content
	appuifw.app.exit_key_handler = exit_key_handler
 
	stats = inbox_stats()
	statsmap = (
		(u"SMS Count", unicode(stats["sms-count"])),
		(u"Unique Contacts", unicode(len(stats["sms-contacts"]))),
		)
 
	for i in statsmap:
		content.style = appuifw.STYLE_BOLD
		content.add(i[0] + u": ")
		content.style = 0
		content.add(i[1] + u"n")
 
	content.add(u"n")
	for k, v in stats["sms-contacts"].iteritems():
		content.style = appuifw.STYLE_BOLD
		content.add(k + u": ")
		content.style = 0
		content.add(unicode(v) + u"n")
 
	app_lock = e32.Ao_lock()
	app_lock.wait()

Which gives me:

Inbox Stats Screenshot

Tags: , , , , , , , , , , ,
Next Page »