User Tools

Site Tools


Writing /var/lib/dokuwiki/data/meta/teaching/ie0117/proyectos/2013/i/way_to_shop.meta failed
teaching:ie0117:proyectos:2013:i:way_to_shop

Way to Shop

You can find the full project here:

Authors

  • Fabian Meléndez Bolaños.
  • Guillermo Cornejo Suarez.
  • Natalia Araya Campos.
  • Juan Carlos Montero Molina.

Introduction

In Costa Rica there's a lack of mechanisms that promote commertial competition and that allows consumers to compare prices between products in an easy and generalized way, in order to make an eficient and smart purchase.

That's why our project is focused in creating a software with the purpose of improving the efficiency of the user's shopping. This will be useful for users with access to internet through their computers or mobile devices.

It also aims to extend the results to facilitate consumers the use of this program and generate them more utilities that depend on aspects such as the user's location, in order to increase the efficiency of the shopping time and its economic cost. Therefore, with this in mind we have work in researching the components that the software will need, for a later development.

It will be implemented what have been done on a first project, in terms of databases and multi-process servers to create different interfaces and complete the server code. This by using two programming languages, python and java.

For the last we want to implement the interface to an application in Android, so it's relevant to know and research about Android development environments, and the creation of apps.

All this in order, to give people a complete tool that allows to increase competitiveness and improve the conditions for consumers from the wide range of offers in the market.

Objectives

General Objective:

  • To establish an environment and basic elements needed to develop a program to facilitate the process of daily purchases and that promotes competitiveness.

Specific Objectives:

  • To create a database with the necessary tables to record the data of users and items and a program able to edit and manipulate it.
  • To develop a pseudo-code for the functioning of the server.
  • To design a communication protocol between the clients and the server.
  • To develop a server capable of withstanding the application.
  • To write the aplication in Python.
  • To establish the development environment for Android.
  • To write the application in Android.

Research

To achieve our objectives, we needed to create databases and servers. For the databases we used MYSQL ( My Structured Query Language 1) ) as our database management system 2).

MySQL is a client / server system that consists of a multi-threaded SQL server, multiple client programs and libraries, administrative tools, and a variety of programming interfaces (APIs). Can also be obtained as a multithreaded library that can be linked into other applications to obtain a smaller, faster, and easier to handle product. And it's server is widely used, very fast, safe, and easy to use. And it has different connectors to JAVA, PYTHON, C, C++, PHP, ODBC and .NET .

In order to create our database and server, we needed to learn how to create them and make them work, that's why we created a tutorial that is divided in two parts: First, you'll find a tutorial for creating databases in MYSQL, and controlling them through python. Later you'll find a tutorial for creating a server with multi-process and how to specify it's communication protocol.

Functioning

As it was exposed previously, the purpose of developing this project is help the users by improving the efficiency of their shopping. By providing them an aplication in which they are able to sign up; check up, seek and add items by scanning barcodes, also they can edit the information of added items. Users will be able to create and save lists with the products they are looking for, and the application will provide them a list with the recommended establishment, the cheapest and the closest, where they can do their shopping; including the price and place to every item.

In order to achieve that and give a better perception of the application's idea, we have proposed the following flowchart.

flowchartwts.jpg

Implementation

Implementing Databases

For our proyect we need to create a database, in order to record: users, items, stores, shopping lists, and it's relations 3).

With this in mind, we decided to create several tables, that will contain this information, in this way:

  • Table Users:

Contains each user's: username, password, name, email, privileges, and number of submits.

  • Table Items:

Contains each item's: barcode, name, brand, quantity, description and an image.

  • Table Stores:

Contains each store's: id (a number), name, latitude, longitude, location.

Also, there are tables for the relations between the previous tables:

  • Table Lists_users:

Contains each list's: id (is a number, ascending), username (to whom it belongs), and it's name (the name by which the user recognizes it).

  • Table Lists_items:

Contains the relation between items barcode and the list-id to which it belongs.

  • Table Items_stores:

Contains the relations between: each item's barcode, the store id, and the price of that item in that store.

We'll explain each table and the way we controlled the whole database through python, in here:

Implementing multi-connection server

For more detailed information about the development of this server check out this page: Writing a multi-process server with python

The server main function will run two functions: the first creates and configures the socket as a server and the second is an infinite loop. Inside this loop the socket will be expecting new connections, once it's achieved it does a fork and then creates an instance of client_server class.
The object client_sver is in charge of answering all the client requests. To manipulate the database it uses the DBmethods file. The constructor of the object receives the socket created after the establishment of communication between server and client. Once the client_server object has been created the function decide is called. This is another infinite loop in charge of receiving all the client request and detecting which is the function that must be executed. The last non specific function is answer() and its work is to inform the client if the work over the database was successful.
The next file are the server and client_server code, further a more user friendly version of the network client.

server.py

#! /usr/bin/env python
 
import socket, os
import client_server
from client_server import Client_server
 
def socket_setup():
	server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	server_address = ('192.168.1.103', 10101)
	server.bind(server_address)
	server.listen(1)
	print "server created and configured"
	return server
 
def wait_connection(server):
	wait_connection = True
	while wait_connection:	
	  print "Online and waiting for new requests"	
	  client_socket, client_address = server.accept()  
	  newproc = os.fork()  
	  if newproc == 0:	
		wait_connection = False
		client_sver = Client_server(client_socket)
		client_sver.decide()	
		client_sver = None
		print 'lost connection'
		os._exit(1)		
 
def main():
	server = socket_setup()
	wait_connection(server)
 
if __name__== "__main__":
	main()

client_server.py

# /usr/bin/env python
 
import socket
import DBmethods as dbm
 
class Client_server:
 
	def __init__(self, client_socket):
		self.client_socket = client_socket
 
	def __del__(self):
		del self.client_socket
 
	def decide(self):
		self.client_socket.settimeout(900)	
		while True:
			try:
				msg = self.client_socket.recv(4096) 
			except socket.timeout:				
				self.client_socket.close()
				break
			instruction = []		
			instruction = msg.split('<>')
			command = instruction[0]		
			if command == 'printf':
				self.printf(instruction)		
			elif command == 'add_user':
				self.add_user(instruction)
 
	def answer(self, status):		
		if int(status):
			answer = 'Success'
		else:
			answer = 'An error has ocurred'
		self.client_socket.sendall(answer)
 
	def printf(self, msg_list):	
		print msg_list[1]
		self.answer(1)		
 
	def add_user(self, msg_list):
		#	write_user(username, password, name, email)
		status = dbm.write_user(msg_list[1], msg_list[2], msg_list[3],msg_list[4])
		self.answer(status)

client.py

#! /usr/bin/env python
 
import socket
 
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.12.199', 10100)
print "socket created"
client.connect(server_address)
print "connection established, write a command"
 
def ask_info():
	info = raw_input()
	return info
	print '/n'
 
exit = False
while not exit:
	command = ask_info()		
	if command == "exit":
		exit = True
	elif command == 'print':
		info = ask_info()
		message = 'printf<>'+info
		client.sendall(message)
		print client.recv(10)		
	elif command == "add_user":
		tmplist = ['username', 'password', 'name', 'mail']
		j = 0
		for i in tmplist:
			print i,
			tmplist[j] = ask_info()	
			j += 1
		info = reduce(lambda x,y: x+'<>'+y, tmplist)
		message = command+'<>'+info
		client.sendall(message)
		print client.recv(10) # check if the operation succeded

Communication Protocol

The communication protocol is a way to synchronize the work made in the client with the one in the server. It is pretty to understand if you follow the functios with the flowchart in mind. The idea is to foresee all the functions that must to be implemented in server and client as well.
The next file is the implementation of this idea.

#This is not a program!! we used the py extension for syntax highlight only. 
#comunication protocol between the server (s) and the client (c)
 
#login
*c-s: login<>username<>password
*s-c: login<>success || login<>invalid username/password combination
 
#sing up
*c-s: signup<>username<>password<>realname<>email
*s-c: signup<>succesful  || signup<>invalid username
 
#item check up
*c-s: seekitem<>barcode<>latitude%/longitude
	#item found
	*s-c: seekitem<>name<>brand<>quantity<>description<>image<>lowestprice<>lowestprice_store<>closestlowerprice<>closestlowerprice_store
		#edit item
			*look below
	#item not found
	*s-c: seekitem<>notfound
		#submit a new item
			*look below		
 
#edit item // submit a new item
		#look for current store
		*c-s: storeinratio<>latitude%/longitude
		*s-c: storeinratio<>storeinratio_1%/storeid<>....
			#client didn't find the store
			*c-s: addstore<>name<>location<>latitude%/longitude
			*s-c: addstore<>succes<>storeid || addstore<>data base error		
		*c-s: edititem<>barcode<>name<>brand<>quantity<>descripton<>image<>price<>storeid #if it is a submit then submititem<>barcode....																						
		*s-c: edititem<>success || submititem<>success
		#add the item to list 
			look below
 
# add item to list
*c-s: requestlists
*s-c: requestlists<>"list#1"%/"list#2"%/...
	#new list
	*c-s: newlist<>listname
	*s-c: newlist<>succesful
	#delete list
	*c-s: delist<>listname
	*s-c: delist<>succesful
*c-s: addtolist<>listname<>barcode     #remove item from list delfromlist<>listname<>barcode
*s-c: addtolist<>succesful
 
 
 
# way to shop!
*c-s: requestlists
*s-c: requestlists<>"list#1"%/"list#2"%/...
	#new list
		*look above (in add item to list)
	#list selected
	c-s: listitems<>listname
	s-c: listitems<>item1%/item2%/...
	# I DON'T KNOW WHAT TO DO IN "ADD" BUTTON
	#save list
	c-s: savelist<>listname<>item1%/item2%/....
	#way to shop
	look below
 
#way to shop
	c-s: waytoshop<>savemytime<>listname
	s-c: waytoshop<>savemytime<>place1/*\totalprice/*\tem1%\item2%\item3....[]place2/*\totalprice/*\tem1%\item2%\item3....[]....
	#similar way for savemymoney

Normally the instructions and the into are separated by <> but in some cases you even need to split that part of the message, this is why some communications uses /\ and [] to split some internal messages.

Server Implementation

The explanation above was just a brief demonstration of Way To Shop server. For many reader this maybe enough, but if you are interested in the full server implementation click the next link:

* Server Implementation

Android on Python, Setting up the Development Environment

The development of mobile applications for Android is usually done using Java as the programming language. Pythonists may not know that since June 2009 it is possible to write applications for Android in Python using SL4A (Scripting Layer For Android).

The SL4A allows developers to edit, run scripts and interact with interpreters directly on the Android device. These scripts have access to many of the APIs of the operating system (OS), but with a greatly simplified interface that makes it easy to:

  • Making calls
  • Texting
  • Scan barcodes
  • Get location and sensor data
  • Use text-to-speech (text-to-speech / TTS)

Between other functions. This project was started by Damon Kohler [] and, like most of Android, SL4A is open-source and distributed under the Apache 2.0 license. SL4A also supports other languages ​​like Beanshell, JRuby, Lua, Perl and Rhino. But in this tutorial we only use Python SL4A.

You'll see that the Python For Android, for the SL4A is just like the one on a PC, and it supports different modules from the standard library, like: glob, httplib, math, os, pickle, shlex, shutil, ssl, string, subprocess, sys, tempfile, time, thread, unittest, urllib, uuid, xml . Even the Zen of Python from Tim Peters. There are modules like the gdata with which you can have access to Google interface services, like creating and editing spreadsheets.

There are also some libraries for using the bluetooth (PyBluez), the red engine, based on events (Twisted), and for astrological data (pyEphem), and lately the PyGame library has been supported!.

There's also a way to use other modules, by adding them on the folder /sdcard/com.googlecode.pythonforandroid/extras/python . So you can use them as if they were part of the standard library.

In this tutorial you'll learn to set your Development Environment, set up a emulator, install SL4A and a basic tutorial for developing App's (GUI's and basic commands).

Installing Android SDK for Debian

For installing the SDK go to:

And follow the steps to get the Android SDK for linux, download it from here:

After downloaded it, it's necessary to extract the files from it. Go to the tools folder and open the executable file “Android”. Select and install the following packages:

  • Android 4.2.2
  • Android 2.2
  • Android 2.3.3
  • Intel x16 Emulator Accelerator

Developing Android App's on Python (With SL4A)

After installing the Android SDK for Android, the emulator is ready to be launched. When it is launched it's necessary to install the SL4A & Python on the Android Emulator following these steps:

  1. Go to the apps center.
  2. Click on settings.
  3. Go to applications.
  4. Activate the Unknown sources.
  5. Go back to emulator's home.
  6. Open the web browser and go to: code.google.com_p_android-scripting
  7. Download the APK by scanning or clicking the barcode on the website.
  8. Install the download.
  9. When the application is installed click on open.
  10. Accept the Usage Tracking.
  11. It will appear an error that says “Failed to create scripts directory. Please check the permissions of your external storage media.” Click OK.
  12. Open the menu. Click on View. Click on Interpreters.
  13. Click the menu and choose Add. Select pyhon 2.6.2. Wait until the download is ready.
  14. Install the download.
  15. When the application is installed click on open.
  16. Click on Install.
  17. Go to the apps center. Click on Gestures Builder.
  18. Click on SL4A. The SL4A is ready to use with python.

You can see a tutorial to install the SL4A & Python on Android Emulator on this video:
Installation of SL4A & Python on Android Emulator

Uploading Scripts

The first problem you may find when you have the scripting layer for android, is that you may need to write the scripts directly from your cellphone or the emulator, this is not appropriate for developing long and quick apps.

Actually you can write the scripts and upload them to your phone or emulator in several ways, one way is writing the script in your computer and generate a QR code with it. For this go to: QR Code Generator from the ZXing Project and select a text content, then in the first line write the name of your python file (“example.py”) then paste your code. This will generate a QRcode. Now in your cellphone, open the SL4A app, press the Menu key, then Add, then select the option “Scan Barcode”.

This option is only helpful if your code is not very extensive, otherwise you won't be able to generate a QR code. There's other option using the Android Debug Bridge, that's in the Android SDK. This file is located in the android-sdk/platform-tools folder, to facilitate its use, include the folder in your $PATH (.bash_profile).
After this, connect your cellphone to your computer with a USB cable (with an emulator this step is clearly not needed). Then you'll be able to send files to your cellphone or emulator with the terminal by doing this command:

$ adb wait-for-device
$ adb push myscript.py /sdcard/sl4a/scripts

There's other options for uploading scripts, like Remote Control using the server support, or using ssh, by email, and other way's that would not be explained in this tutorial.

Basic Commands

As you can imagine, programming apps in python its really simple, here we are gonna explain a few basic commands, but you can see the full API Rererence here.
The first thing to do its to import the Android library

import android
droid = android.Android()

After this, the app can go anywhere and anyway you want it to, just like a regular script. But there's a few interesting commands we would like to emphasize in. For example the makeToast command, its a simple way to show a little message.

droid.makeToast("Hellow World!")

There are a lot of things that are really useful and simply to do in the SL4A. For example, a barcode scaner app, that uses the Zxing Barcode Scanner App (Needs to be installed).

#We scan the barcode
code = droid.scanBarcode()
#Extract the code
barcode = code[1]['extras']['SCAN_RESULT']

Also, you can do things like getting the GPS coordinates in a few lines!

#We start locating the client
droid.startLocating()
time.sleep(10)
location = droid.readLocation().result
 
#In case that the location failed, we get the last known location
if (location == {}):
	location = droid.getLastKnownLocation().result
 
#When we already have one known location
if (location != {}):
	try:
		result = location['gps']
	except:
		result = location['network']
        #We extract the latitude and longitude from the lecture
        latitude = result['latitude']
        longitude = result['longitude']
        #If your country is supported, you can get an address from the geocode proyect
        address = droid.geocode(latitude, longitude).result
 
#We stop locating
droid.stopLocating()

There are a few graphical resources, especially dialogs. You can create a loading dialog

#We start a loading alert
droid.dialogCreateSpinnerProgress("Loading", "Please Wait")
droid.dialogShow()

You can create an alert box or a question and respond to id 4).

droid.dialogCreateAlert("I like swords.","Do you like swords?")
droid.dialogSetPositiveButtonText("Yes")
droid.dialogSetNegativeButtonText("No")
droid.dialogShow()
response=droid.dialogGetResponse().result
droid.dialogDismiss()
if response.has_key("which"):
  result=response["which"]
  if result=="positive":
    print "Yay! I like swords too!"
  elif result=="negative":
    print "Oh. How sad."
elif response.has_key("canceled"): # Yes, I know it's mispelled.
  print "You can't even make up your mind?"
else:
  print "Unknown response=",response

The print command just prints in the terminal, just like in a computer.

GUI's

The Android Scripting Layer doesn't have a real graphical support, therefore we need to seek alternative ways to develop a GUI (Graphical User Interface), PySide is really good option for developing Android Apps GUI. PySide is a Python binding of the cross-platform GUI toolkit Qt. It is one of the alternatives for GUI programming in Python to Tkinter, which is bundled with Python.

Another option for developing a GUI for your application is using the XML code for writing layout's for your app, and them use them in your code. A really easy way of getting the XML code for a layout is building the layout in with the Eclipse + ADT pluggin (The oficial IDE for android), you can get it in the official Android page.

What we'll use will be the full screen interface, that is a new, experimental feature that allows you to define and display a Layout, and respond to button clicks and other key events. This feature is available with the r5 release of the SL4A.

For this, you must create the layout you want in XML code, and the use the droid.fullShow() comand to display it. And trigger an event loop decider in order to react to the events. You can use the droid.fullQuery() or droid.fullQueryDetail() functions to access information from the screen. Also you can use the droid.fullSetProperty() function to change things in the screen. For more information visit FullScreenUI Tutorial Like this:

def eventloop():
  while True:
    event=droid.eventWait().result
    print event
    if event["name"]=="click":
      id=event["data"]["id"]
      if id=="button3":
        return
      elif id=="button2":
        droid.fullSetProperty("editText1","text","OK has been pressed")
      elif id=="button1":
        droid.fullSetProperty("textView1","text","Other stuff here")
        print droid.fullSetProperty("background","backgroundColor","0xff7f0000")
    elif event["name"]=="screen":
      if event["data"]=="destroy":
        return
 
 
layout="""<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/background"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent" android:background="#ff000000">
        <LinearLayout android:layout_width="match_parent"
                android:layout_height="wrap_content" android:id="@+id/linearLayout1">
                <Button android:id="@+id/button1" android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:text="Test 1"></Button>
                <Button android:id="@+id/button2" android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:text="Ok"></Button>
                <Button android:id="@+id/button3" android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:text="Cancel"></Button>
        </LinearLayout>
        <TextView android:layout_width="match_parent"
                android:layout_height="wrap_content" android:text="TextView"
                android:id="@+id/textView1" android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_vertical|center_horizontal|center"></TextView>
        <EditText android:layout_width="match_parent"
                android:layout_height="wrap_content" android:id="@+id/editText1"
                android:tag="Tag Me" android:inputType="textCapWords|textPhonetic|number">
                <requestFocus></requestFocus>
        </EditText>
        <CheckBox android:layout_height="wrap_content" android:id="@+id/checkBox1" android:layout_width="234dp" android:text="Howdy, neighbors." android:checked="true"></CheckBox>
</LinearLayout>
"""
print layout
print droid.fullShow(layout)
eventloop()
print droid.fullQuery()
print "Data entered =",droid.fullQueryDetail("editText1").result
droid.fullDismiss()

Android App

If you've followed this tutorial, then you now know how to develop simple scripts and run them in your phone, now we'll explain our client for android of the Way To Shop application. You can see the explanation of our code in here:

Packaging and distributing the application

Android applications are typically distributed in a single file or package with an .apk extension. An Android package is essentially an archive file similar to a .jar or .zip file. To package our application it's necessary to use Eclipse (a multi-language Integrated Development Environment).

The first thing to do is download the script template file from the SL4A project site (http://android-scripting.googlecode.com/hg/android/script_for_android_template.zip).

Next, make a copy of the template in Eclipse by right-clicking the project and then choosing Copy from the menu.

Next, right-click in an empty area of the Package Explorer window and choose Paste from the menu. Give the new project a name and then click OK. In our case is called WayToShop.

Now comes the part where we insert our script called AndroidScript. Make a copy of the script and paste it into the res/raw directory. The easiest thing to do here is delete the existing script.py file and rename the script to script.py. That way it won’t be necessary to change any of the other locations that reference script.py. You’ll also need to rename the default package com.dummy.fooforandroid/WayToShop.

For that it can be used the Eclipse Refactor/Rename tool to do this. Then it's necessary to update the package property in AndroidManifest.xml to reference WayToShop.

At this point, we're able to go through the build-and-export process to create the WayToShop.apk.

References

1)
es.wikipedia.org/wiki/MySQL
3)
Each item is in a store, each user has a series of lists, each list has it's items, etc
teaching/ie0117/proyectos/2013/i/way_to_shop.txt · Last modified: 2022/09/20 00:08 (external edit)