cherrypy

Basic concept on CherryPy

A python script called hello.py is created as follows:

import cherrypy

class HelloWorld:
def index(self):
return "Hello world!"
index.exposed = True

cherrypy.quickstart(HelloWorld())

The application can be started at the command prompt by typing $ python hello.py
At the web browser, “Hello World” can be seen when it is directed to http://localhost:8080.

import cherrypy // imports the main CherryPy module

class HelloWorld: //declare a class named HelloWorld
def index(self): // contains a single method called index which will be called when the root URL for the site is requested (http://localhost/)
return “Hello world!” // return the contents of the web page (“Hello world!” string)
index.exposed = True // to tell CherryPy that index() method will be exposed and only exposed methods can be called to answer a request. This allows user to select which methods will be accessible via the web.

cherrypy.quickstart(HelloWorld()) // mounts an instance of the HelloWorld class and starts the embedded webserver. It will run until explicitly interrupted.

When the web application is executed, the CherryPy server will listen on localhost at port 8080.
The default configuration of CherryPy server can be overridden by using another configuration file or dictionary.

When it receives the request for the URL http://localhost:8080, it searches for the best method to handle the request, starting from the first instance (HelloWorld). The root of the site is automatically mapped to the index() method. The HelloWorld class defines an index() method and exposes it (@cherrypy.expose). Therefore CherryPy will call HelloWorld().index() and the result of the call is returned to the browser as the contents of the index page for the website.

In order for CherryPy to call a page handler, it has to identify which and where to call for a given Uniform Resource Identifier (URI). A Dispatcher object is used to understand the arrangement of handlers and to find the appropriate page handler function.
The arrangement of CherryPy handler by default is a tree which enables the config to be attached to a node in the tree and cascade down to all children of that node. The mapping of URI to handlers is not always 1:1 and thus it offers more flexibilities.

Updates!

Updates!

Hey guys. It has been ‘another’ a while since i last update about my progress. (Kind of upset with no like or comment actually!) :p

Anyway, so far I’ve managed to get the status table to display properly – user can select an option, key in a value and add to the dynamic table (happy!). Then the Javascript will query for status. Hmm, i have stuck at this point for quite some time. There are a few things to note here:

  1. It has to check what are the entries in the table.
  2. Then it sends that query to the device system, row by row. – requires delay! Because raspberry Pi isn’t that fast to pick up the replies.
  3. Then it has to continuosly monitor the status. – requires a loop!

For delay, i used setTimeout() as such:

var checked = $('#status_table tr [id^="monitor_"]:checked');
setTimeout(function(){
if(++i <checked.length) loop(i);
},3000);

where checked.length will refer to the number of checked checkbox and 3000 (in ms) is the delay i set. I found out that 1000 (1 second) is too fast for Raspberry Pi. So to be safe, i used 3 seconds instead.

 

For looping, i used setInterval() as such:

bigloop=setInterval(function(){

//the looping function above and blah

}, index*4000);

 

Well currently i still have not figure out how to use checked.length instead of index to multiply 4 seconds. I chose 4 seconds is because i would like to give it more time allowance to execute the commands. The only problem with index*4000 is that if the list is long and the index is large, the initial waiting time is long too.

You can see my working fiddle here: http://jsfiddle.net/qJdaA/2/

Also, I have a “monitor” button to make things easier. The monitoring process will only starts when the button is clicked. Then to prevent multiple clicks which would mess things up, I disabled the button when the monitoring process is running. I would like to thank my junior for giving me this suggestion! I was using colour indicator (which was very weird and ugly) to indicate the button status.Β  hahaha.Β  See my printscreen below.

Checking if there is item in the list.
if (checked.index()==-1){
$('#monitor').button('disable');
}else{
$('#monitor').button('enable');

The above is applicable for jQuery Mobile. For normal jQuery or Javascript, i use:
$('#monitor').attr('disabled','true');
and
$('#monitor').removeAttr('disabled');

web app

The button is disabled initially.

web app

When the first item is added, the monitor button is enabled.

web app

When the monitoring starts, the monitor button is disabled to prevent user from clicking it again

web app

When a row is removed, the looping interval is cleared and the monitor button is enabled again.

There is a div for myself to monitor what is going on in the loop (as can be seen in the picture above), but it is tedious to scroll down and down or refresh. so i created a clear button.

web app

The clear button clears off the testing div.

I’ve manage to settle the output status, zone_input status, and even counter value!
Well, the process seems a bit complicated to me but i shall read more about it and post about what i’ve learnt later.

How to Reset HTML Form using jQuery

Reset button makes life easier but can be disastrous if you accidentally click on it. opps.

1. Create the reset button in HTML:
<input type ="reset" id="reset" value="Reset"/>
// id and value is your own choice. Value is what that appears on the button.

2. In your javascript:
$('#reset')[0].reset();
//’#reset’ is the id that you set.

Note: (Special thanks to Michael for explanation on this little jQuery magic.) [0] is because it is getting a list from the selector. So now it is getting the zeroth item from the selector.

CherryPy Progressing well with Raspberry Pi

Thanks to Michael, i have a better understanding on CherryPy. It is rather amazing to use jQuery to create little boxes and buttons on a webpage. Hmm, i still have not figure out how to print the screen of Raspberry Pi… Anyway it looks pretty cool!

I have solved the problem of getting the input from the virtual keypad and use it to log into Comfort system. it is all about setting the right id and using the right id at the right place.

Then, i encounter another problem of different def functions causing those control buttons under different functions unable to send command (because of the log in?) Okay, sound confusing.

Moving on to web2py for the time being! >:)

WEIRD Web2py

Morning Monday.

So i was renown for being a “Spoiler” because i always cant’ wait to tell my sisters what’s going to happen in the drama series. 😑 So, i spoilt quite a few things last week including my sd card and SIM card. My Web2py web app couldn’t work as well.

I asked around in the forum and Google group, desperately finding answers. Then, i reconnect everything and hey, where is the error? ARE YOU SERIOUS? i logged into the Comfort system from my web2py app?! Then, i added another serial command to turn on the light… it turned on. i was shocked. Seriously, totally have no idea what is going on. I didn’t change anything, did I?

Anyway, now i will start hesitating between web2py and cherrypy, again.

Update on cherrypy progress, i manage to get the keypad out but have not able to use it to let user to sign in.

Update on my KDrama, YES, i have finished watching “Rooftop Prince” and it is extremely nice. I cried non-stop towards the end. Such a wonderful and touching story. Will update on it in a post next time! T_T

And Thank God for Easter Day. ❀ Gloria! Glory to the Lord! πŸ˜‰

jQuery Keypad

Found an awesome keypad for my application here.

I have added the keypad to the sample web app successfully. Now that i need to use the keypad to Log in to the device by sending the log in information to the Raspberry Pi webserver and the server will send to the device through the serial port.

i find it hard to apply what i’ve just learnt. the examples and tutorials are too limited. or my understanding and capability are too limited. Too dependant. 😦

Hello web2py

I have been lazying out on Raspberry Pi recently. Stuck at getting the web app on web2py to open the port at ttyAMA0. However it works fine on CherryPy.

Why. Why. Why.

Would it be better to just focus on CherryPy? :/ but i think Web2Py is newer and probably better and easier!
That is if and only if i am determined enough to finish reading (and digesting) through the 583 pages web2py manual. But it is so tiring to read it through the screen and time-wasting to study during working hours. If only i have an iPad or something.

Wait, did i just think of the Amazon Kindle or something? Haha, right. I should do something meaningful in the train while on my way to work, rather than sleeping. How about knitting? (That’s too outstanding. You probably wouldn’t want the whole pack of Sardine (we call the commuters that) to stare at you and start guessing your age.)

Not sure if it is a good idea to learn web2py and cherrypy concurrently. just hope that Mr Massimo can solve my problems soon.

Websites KIV:
Your first CherryPy application

CherryPy Tutorial

The CherryPy Documentation

Work related stuffs to do tomorrow:
– testing Z-wave responses (forgot to do it today!!!)

UnderstoodΒ  some Z-Wave problems today.

Other stuffs to do tonight:
– unofficial strategy planning with new team
– reply business emails
– EH, FINISH UP MY PROJECT REPORT!

– revamp website too.

CherryPy Progress!

Good Day! i got stuck in testing the new Z-Wave firmware so here I am, back for more CherryPy!

Thanks to Mefarmer and ax25 who explained to me about what’s going on with the CherryPy and gave me clues on how to proceed! It is a nice of motivation. πŸ™‚

Let me restart my CherryPy journey and you can refer to my discussion with mefarmer in this forum thread. Do download the mobile_website.zip from there too as i could not upload the file here.

Before that, i forgot to mention about jQuery Mobile!! i think it is an awesome app. Check out the themeroller! Awesome awesome!! i’m so excited to make some web apps!!!! Wait. is web2py totally different from this? :O

The last time i edited the tutorial.conf file by changing the port number and tools.staticdir.root. But the web app wouldn’t show up when i type in the localhost:portnumber. Today, i changed the port number to 8020 which is not in used by any server. I think Web2py has taken up localhost:80 by default and :8080 seems to have some error… i did use it to display “Hello world” from the tutorial file included with the installation.

Anyway, moving on to remote_control.py.
Adding #!/usr/bin/python will allow user to run the script automatically by typing python myscript.py in the terminal. remote_control.py, when run, will return a html file (webpage) which shows a sleek nice black layout with 3 buttons in the first row and a slider in the second row.

The jQuery Mobile framework is using a block style class convention called ui-grid.
There are four preset configurations layouts that can be used in any situation that requires columns:

  • two-column (using the ui-grid-a class)
  • three-column (using the ui-grid-b class)
  • four-column (using the ui-grid-c class)
  • five-column (using the ui-grid-d class)

Within the grid container, child elements are assigned ui-block-a/b/c/d/e in a sequential manner which makes each “block” element float side-by-side, forming the grid. The ui-block-a class essentially clears the floats which will start a new line (see multiple row grids, below).

To display the 3 buttons, here is the code (for one of the buttons):

<div class ="ui-grid-b">// 3 columns
block
block (refer below)
</div>

<div>
<button type="button" id="new_1" data-role="button" data-transition="fade" >
new_1 //word on the button
</button>
</div>

Read more here.

As for the slider, the data-role will be “slider” and it has more things to set (e.g option) (refer remote_control.py)

Inside the html file shown in the example, we can add “scripts” in the form of “script src” (which direct to a script file) or “script type” which we can directly add in the script below it. in this case, a javascript was included. this will get the clicks and send them to the server using ajax:

$("#unique_id").click(function () {$.post('/request',{key_pressed:"unique_id"})});

$(“#slider_id”).change(function () {$.post(‘/request’, {key_pressed:”slider_id”+$(this).val()})});

Every button has an unique ID. Then the javascript sets up an event handler that looks for a “click” event with that unique ID. When there is a “click” event, it will do an ajax “post” to “http://localhost/request&#8221; which will send JSON data {key_pressed:”unique_id”}

Server will get the “post” and route it to the “request” function (in the remote_control.py itself). The JSON will be passed in as a dictionary. Inside the “request” function, we get the dictionary as “data” and look for the key “key_pressed”. The value we get from that, is the unique ID we passed in from the javascript ( {key_pressed:”unique_id”} ). in the example, we simply just send ID and use an if statement to look for matching values and print it out.
if key == “new_1”:
# you can do anything you want right here
print “new_1”

Now, to test my own application, this is what i do:
1. Login test
– import serial and time
– in the “request” function, i added

serialport = serial.Serial("/dev/ttyAMA0/", 9600, timeout=0.5)
serialport.write("\x03LI1234\x0D")
response = serialport.readlines(1)
print response
time.sleep(1)

– somehow i need to use a new port number. then i run the python script.
– it’s a success! i got the reply from the device connected to its serial port.

2. other buttons test
– here comes the challenge. serialport belongs to the if key ==”start” only. Does that mean i have to open the serial port everytime i press on any button? well that’s definitely not the best way. I can’t seem to find anywhere to insert that line (serialport =serial.Serial(….))
outside the function? global name “serialport” is not defined
inside the function, outside the “if”? local name “serialport” is not defined.

so in the end, i insert

serialport = serial.Serial("/dev/ttyAMA0/", 9600, timeout=0.5)

in every “if” and “elif” and it works~ whenever i slide the bar to “on”, the testlight turns on, and when i slide to “off”, the testlight turns off. Happy! πŸ˜€ Arming and disarming works too!! lovely milestone today! πŸ™‚

IMPORTANT! while i edit the python file, i did not shutdown the server. After i saved my changes, the server will “re-spawn”? i take that as a restart. haha, CherryPy coming back to life huh?

CherryPy!

Yesterday i got to know a new friend called CherryPy, a lovely sweet lady? No, it’s a “minimalist Python Web Framework”. Someone replied to my forum topic and he explained quite a lot about web application.

CherryPy seems to be a good alternative to web2py although she is older.
1. So, let’s start off by installing CherryPy in our RaspberryPi by downloading the tar.gz file from here.

UPDATE: can just install using sudo pip install CherryPy

2. Save it in your home/pi directory and open up the LXTerminal.

3. Type:
tar -xzvf CherryPy-3.2.2.tar.gz

4. Rename the file to CherryPy for ease of access

5. Then go to the directory created by the file extraction
cd CherryPy

6. Type: (user has to be root)
sudo python setup.py install

7. Run the first sample website by going to cherry/tutorial directory and type “python tut01_helloworld.py”
cd cherrypy/tutorial
python tut01_helloworld.py

8. Open your browser (Midori or iceweasel or something else on R-Pi) and type http://localhost:8080 or http://127.0.0.1:8080 at the address bar.

There you go, Hello World! πŸ™‚

To stop the server, press CTRL+Z. CTRL+C.

** create a new “shutdown” function using “cherry.engine.exit()” and display it as a link on the web app – when clicking that shutdown link, the server will shutdown and the port will be freed. πŸ˜‰

Now i will download the file from the forum and see what he has got for me!

1. Go back to the home directory (where you have saved the zip file)
unzip mobile_website.zip
2. Then create a new folder named mobile_website (or something else of your choice)
3. Move the extracted files into the folder.
4. Go to that folder direcotry in terminal, type:
gedit remote_conrol.py
(it is also possible to edit the file directly using IDLE or other editors)
5. Add in #!/usr/bin/python at the top of the page
6. Edit the tutorial.conf
nano tutorial.conf

Change tools.staticdir.root =”/home/pi/mobile_website”
CTRL+O
CTRL+X
6. Run python remote_control.py to start the server or double click on the remote_control.py
(Ok, it doesn’t work on my R-Pi)
ChannelFailures: IOError (“Port 80 not free on ‘0.0.0.0’”)

Stuck and waiting for someone to help me in the forum. 😦