======== Way to Shop ======== You can find the full project here: * [[https://github.com/gmocornejos/Way_To_Shop | Way To Shop Proyect]] ====== 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 ((es.wikipedia.org/wiki/MySQL)) ) as our database management system ((http://en.wikipedia.org/wiki/Database)).\\ 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**. * [[teaching:ie0117:proyectos:2013:i:way_to_shop:databases_in_mysql|Databases in MYSQL]] * [[teaching:ie0117:proyectos:2013:i:way_to_shop:multi-process_server| Multi-connection Server]] ====== 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. \\ {{ ie0117_proyectos_2013: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 ((Each item is in a store, each user has a series of lists, each list has it's items, etc)).\\ 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: \\ * [[teaching:ie0117:proyectos:2013:i:way_to_shop:waytoshop_database|Database implementation]] ==== Implementing multi-connection server ==== For more detailed information about the development of this server check out this page: [[teaching:ie0117:proyectos:2013:i:way_to_shop:multi-process_server|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: *[[teaching:ie0117:proyectos:2013:i:way_to_shop:serverimplementation| 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: \\ * [[http://developer.android.com/sdk/index.html]]\\ And follow the steps to get the Android SDK for linux, download it from here:\\ * [[http://dl.google.com/android/android-sdk_r22.0.1-linux.tgz]]\\ 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:\\ -Go to the apps center. -Click on settings. -Go to applications. -Activate the Unknown sources. -Go back to emulator's home. -Open the web browser and go to: [[..:..:..:ie0117_proyectos_2013:code.google.com_p_android-scripting]] -Download the APK by scanning or clicking the barcode on the website. -Install the download. -When the application is installed click on open. -Accept the Usage Tracking. -It will appear an error that says "Failed to create scripts directory. Please check the permissions of your external storage media." Click OK. -Open the menu. Click on View. Click on Interpreters. -Click the menu and choose Add. Select pyhon 2.6.2. Wait until the download is ready. -Install the download. -When the application is installed click on open. -Click on Install. -Go to the apps center. Click on Gestures Builder. -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:\\ [[http://www.youtube.com/watch?v=1O39oALC83w | 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: [[http://zxing.appspot.com/generator/ | 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 [[https://code.google.com/p/android-scripting/wiki/RemoteControl |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 [[https://code.google.com/p/android-scripting/wiki/ApiReference#dialogCreateSpinnerProgress | 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 ((https://code.google.com/p/android-scripting/wiki/UiExamples)). 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. [[http://en.wikipedia.org/wiki/PySide | 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 [[http://developer.android.com/intl/es/sdk/index.html | 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 [[https://code.google.com/p/android-scripting/wiki/FullScreenUI|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=""" """ 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: * [[teaching:ie0117:proyectos:2013:i:way_to_shop:androidclient| Android Client]] ====== 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 ====== -[[https://github.com/gmocornejos/Way_To_Shop | Way To Shop Proyect (GitHub)]] -[[https://code.google.com/p/android-scripting/ | Scripting Layer For Android]] -[[http://www.youtube.com/watch?v=1O39oALC83w | Installing SL4A. Video]] -[[http://www.ibm.com/developerworks/opensource/library/mo-python-sl4a-1/index.html | Set up your development environment for the SL4A ]] -[[https://code.google.com/p/android-scripting/wiki/ApiReference#dialogCreateSpinnerProgress | API Reference for the SL4A]] -[[https://code.google.com/p/android-scripting/wiki/RemoteControl | Remote Control for Android Devices]] -[[https://code.google.com/p/android-scripting/wiki/FullScreenUI | Full Screen User Interfaces on SL4A]] [[teaching:ie0117:proyectos:2012:i:linux_2013| Back to projects]] \\ [[teaching:ie0117:proyectos:2013:i:way_to_shop| UP]] \\