Source

Raspberry Pi GPIO Web Control / README.md

Sebastian Bub 49f77d1 
Sebastian Bub f815b33 
Sebastian Bub fc14f28 
Sebastian Bub c289baf 

Sebastian Bub de5a980 
Sebastian Bub c289baf 
Sebastian Bub de5a980 
Sebastian Bub 2bd3052 

Sebastian Bub c289baf 
Sebastian Bub 2bd3052 
Sebastian Bub 6f87766 
Sebastian Bub da90dd3 
Sebastian Bub c289baf 


Sebastian Bub 2bd3052 
Sebastian Bub 5113434 

Sebastian Bub c289baf 
Sebastian Bub 5113434 
Sebastian Bub c289baf 

Sebastian Bub 49f77d1 
Sebastian Bub c289baf 
Sebastian Bub 330c967 
Sebastian Bub deb0084 
Sebastian Bub 2bd3052 
Sebastian Bub 4e5cc23 
Sebastian Bub c289baf 

Sebastian Bub fe73370 
Sebastian Bub 330c967 
Sebastian Bub a873bf5 
Sebastian Bub 3e8ea8f 

Sebastian Bub fe73370 


Sebastian Bub 3e8ea8f 
Sebastian Bub 49f77d1 
Sebastian Bub 3e8ea8f 
Sebastian Bub c289baf 

Sebastian Bub da90dd3 
Sebastian Bub c289baf 
Sebastian Bub deb0084 

Sebastian Bub c289baf 

Sebastian Bub a873bf5 










Sebastian Bub 243a6f0 
Sebastian Bub c289baf 
Sebastian Bub 6e1b160 
Sebastian Bub c289baf 
Sebastian Bub d2454f0 
Sebastian Bub c289baf 
Sebastian Bub 6e1b160 
Sebastian Bub c289baf 
Sebastian Bub 6e1b160 
Sebastian Bub c289baf 
Sebastian Bub de5a980 
Sebastian Bub c289baf 
Sebastian Bub 243a6f0 
Sebastian Bub c289baf 
Sebastian Bub 243a6f0 
Sebastian Bub c289baf 
Sebastian Bub 243a6f0 
Sebastian Bub c289baf 
Sebastian Bub 243a6f0 
Sebastian Bub c289baf 
Sebastian Bub 243a6f0 
Sebastian Bub c289baf 
Sebastian Bub 243a6f0 


Sebastian Bub 5113434 
Sebastian Bub 54fd6fa 

Sebastian Bub 243a6f0 
Sebastian Bub 49f77d1 
Sebastian Bub 243a6f0 
Sebastian Bub c289baf 
Sebastian Bub 243a6f0 
Sebastian Bub f09d7ae 
Sebastian Bub c289baf 
Sebastian Bub 6e1b160 

Sebastian Bub 49f77d1 
Sebastian Bub deb0084 
Sebastian Bub 2bd3052 
Sebastian Bub 49f77d1 

Sebastian Bub de5a980 

Sebastian Bub 49f77d1 


Sebastian Bub 2bd3052 

Sebastian Bub 6e1b160 
Sebastian Bub da90dd3 
Sebastian Bub fe73370 
Sebastian Bub 2bd3052 

Sebastian Bub 5113434 
Sebastian Bub 1210294 
















Sebastian Bub 54fd6fa 




Sebastian Bub 5113434 



















Sebastian Bub 87fee5b 
Sebastian Bub 5113434 


Sebastian Bub 87fee5b 
Sebastian Bub 5113434 
Sebastian Bub 87fee5b 
Sebastian Bub 5113434 
Sebastian Bub 87fee5b 
Sebastian Bub 5113434 
Sebastian Bub 87fee5b 
Sebastian Bub 5113434 
Sebastian Bub 87fee5b 
Sebastian Bub 5113434 
Sebastian Bub 76f6a9d 
Sebastian Bub 87fee5b 


Sebastian Bub 76f6a9d 
Sebastian Bub 87fee5b 




Sebastian Bub 5113434 
Sebastian Bub 76f6a9d 











Sebastian Bub 4e5cc23 
Sebastian Bub 5113434 


Sebastian Bub 87fee5b 
Sebastian Bub 5113434 




Sebastian Bub 2bfdf01 
Sebastian Bub 5113434 


Sebastian Bub 87fee5b 




Sebastian Bub da90dd3 
Sebastian Bub 76f6a9d 

Sebastian Bub 2bd3052 
Sebastian Bub 76f6a9d 
Sebastian Bub 2bd3052 
Sebastian Bub 76f6a9d 
Sebastian Bub deb0084 
Sebastian Bub 76f6a9d 


Sebastian Bub 2bfdf01 
Sebastian Bub 76f6a9d 






Sebastian Bub deb0084 
Sebastian Bub 76f6a9d 
Sebastian Bub deb0084 
Sebastian Bub 76f6a9d 


Sebastian Bub deb0084 




Sebastian Bub 76f6a9d 
Sebastian Bub 145abd0 



Sebastian Bub 2bd3052 
Sebastian Bub 145abd0 
Sebastian Bub 2bd3052 
Sebastian Bub 145abd0 
Sebastian Bub 2bd3052 
Sebastian Bub 145abd0 

Sebastian Bub c289baf 










Sebastian Bub fe73370 
Sebastian Bub c289baf 


# RASPBERRY PI GPIO WEB CONTROL INTERFACE

## A Java webapp to control your GPIO ports of the Raspberry Pi using http


## What is raspberry-pi-gpio-web-control?

raspberry-pi-gpio-web-control is a lightweight java based web application to control your GPIO ports
of your Raspberry Pi over http. It is based on documentation at 
[elinux.org: RPi Low-level peripherals](http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28Shell_script.29)

It is tested with [Winstone Servlet Container](http://winstone.sourceforge.net/), but any
other servlet engine will probably do, too.


### Features:

* Every port can be set as input, output or analog input (requires a simple circuit based on [raspberrypi-spy.co.uk: Reading Analogue Sensors](http://www.raspberrypi-spy.co.uk/2012/08/reading-analogue-sensors-with-one-gpio-pin/)).
* Output ports can be set conditionally on values of input ports (i.e. darknessSensor1in==1&lamp1out=1, see cron.conf).
* You can give each port a custom name to make your client look better.
* You can define a default state on output ports.
* You can define a blocking time for an output port (so it is not switched to
  fast in case the user makes a request twice).
* You can define a toggle time for an output port (i.e. if you want to turn
  a port on for a defined period of time, it can be done with a single request). 
* You can set a simulation mode for testing your client.
* Controlling multiple ports in one requests are set one after another, but the code
  is optimized and nothing unnecessary is done in between (it takes about 2-5ms on an idle Raspberry Pi to set all 17 ports, some artificial load (e.g.'find /' in the background) will slow it down to 10-15ms).
* Cronjobs (exact to the second) for output ports are based on [quartz-scheduler.org](http://quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/crontrigger). Output ports can be set conditionally and you have a simple but powerful semaphore mechanism.
*   You may define your own variables with a prefix VIRTUAL which are persisted in memory (unknown virtual variables default to "0").

### Planned Features

* Automated tests
* If GPIO ports are used to represent binary output values, blocking single ports is dangerous: Delayed/Queue requests
* Custom hooks (pre/post), e.g. for notifications
* More status and configuration information requestable via json (disengageable)

### Possible Unplaned Features

* Bit sequences (especially with AUTO.TOGGLE.TIME) for serial output or to control a servo (probably an SPI interface)
* Some kind of PLC (Programmable Logic Controller)
* Suggestions are welcome


## Project Status

The project has started and I use it by myself mainly for
simple output (manually and with cronjobs). If I had to give it a release number, I would say it is a 0.85 release. Bug reports and feature requests are welcome.


## Getting Started (from tgz)

1. [Download](https://bitbucket.org/sbub/raspberry-pi-gpio-web-control/downloads) the latest version of the package as raspberry-pi-gpio-web-control-[version].tgz

2. Extract it using `tar xzf raspberry-pi-gpio-web-control-[version].tgz`

3. Install Java, e.g. `sudo apt-get install openjdk-6-jdk`

4. Go on with **7. Getting Started (from Source)**


## Getting Started (from Source) - PREFERRED METHOD!

1. Install Java, e.g. `sudo apt-get install openjdk-6-jdk`

2. Check that you can call java from the command line, e.g.  java -version

3. Install Maven2 `sudo apt-get install maven2`

4. Install Mercurial `sudo apt-get install mercurial`

5. Get the project `hg clone https://bitbucket.org/sbub/raspberry-pi-gpio-web-control`

6. Change working directory to raspberry-pi-gpio-web-control with `cd raspberry-pi-gpio-web-control`

7. Build the project `mvn package` (It takes about 3-7 minutes to build on Raspberry Pi).

8. **Get [Winstone Servlet Container at http://winstone.sourceforge.net/](http://winstone.sourceforge.net/)** and put the jar in the same directory as the start.sh.

9. Check the location and name of WINSTONE_JAR in start.sh

10. **Copy gpio.conf.MUST_BE_CHANGED** to gpio.conf and configure it.

11. Start the servlet container `sudo ./start.sh`. You may have to mark the scripts executable `chmod a+x start.sh stop.sh` first.

12. Make a request, e.g. **[http://raspberrypi:8080/handle?g0=1&g1=0](http://raspberrypi:8080/handle?g0=1&g1=0)**

    It will return {"g1":0,"g0":1}.
  
13. Read the log file logs/raspberry-pi-gpio-web-control.log
    
14. Stop the servlet container `sudo ./stop.sh`. Make sure that there are no old Winstone processes running with old configurations! You can check that with `ps -ef| grep java`. In case you can not stop the process and you have to stop it with kill -9, you may consider rebooting as the GPIOs are still exported and the next start may fail.

15. To enable cronjobs, you need to copy cron.conf.MAY_BE_CHANGED to cron.conf and configure it


## Going Productive

* Make sure you **disable simulate mode**.
* Turn down logging after testing in log4j.properties (this is important for performance on your Raspberry Pi).
* A simple init.d script is also provided in file src/main/resources/init.d/gpio-winstone which can be installed with the follwing commands:

```
chmod a+x /home/pi/raspberry-pi-gpio-web-control/src/main/resources/init.d/gpio-winstone
sudo cp /home/pi/raspberry-pi-gpio-web-control/src/main/resources/init.d/gpio-winstone /etc/init.d/gpio-winstone
sudo update-rc.d gpio-winstone defaults 3 3
```

**Do not forget that your GPIO ports may be operated by this process now (even after reboot)!**


## Configuration and Logging and Debugging

* To change logging check log4j.properties and start.sh.
* For configuration check gpio.conf, cron.conf and start.sh

## Updating the Software

If you already installed a version from source, it is very easy to get new features and update to the latest release:

1. Change working directory to raspberry-pi-gpio-web-control with `cd raspberry-pi-gpio-web-control`

2. Get the latest release `hg pull`

3. Update your local repository `hg update`

4. Stop the servlet container sudo ./stop.sh.

5. Rebuild the project `mvn package`

6. Start the servlet container `sudo ./start.sh` 


## An iPhone Client

If you also need a client for your iPhone or iPad, you may want to have look at my free iPhone client: [iControl Web](https://itunes.apple.com/de/app/icontrol-web/id580659303?mt=8).


## Sampe Usage

Imagine you have the following configuration in gpio.conf:

`GPIO.0.DIRECTION=IN`

`GPIO.0.NAME=darknessSensor1in`

`# lamp1out has a "momentary contact switch"`

`GPIO.1.DIRECTION=OUT`

`GPIO.1.NAME=lamp1out`

`GPIO.1.OUT.DEFAULT.STATE=0`

`GPIO.1.OUT.AUTO.TOGGLE.TIME=250`

`GPIO.1.OUT.BLOCK.TIME=10000`

The darknessSensor1in will return 1 if it is "dark" and 0 during daylight.

### Manual Control

In order to set the lamp manually you could send the following request to turn on the lamp: `http://raspberrypi:8080/handle?lamp1out=1`. Response would be `{"lamp1out":1}`. GPIO.1 will be set to 1 and after 250ms, it toggles back to 0. You can not control the gpio for 10 seconds.

In order to check the sensor manually you could send the following request: `http://raspberrypi:8080/handle?darknessSensor1in=IN`. Response could be `{"darknessSensor1in":1}`. The state of the GPIO.0 is 1.

In order to check the state of the lamp manually you could send the following request: `http://raspberrypi:8080/handle?lamp1out=IN`. Response could be `{"lamp1out":1}`. The lamp is on and the state of the GPIO.1 is 1.

You could also send a conditional manual request (turn light on if it is dark enough): `http://raspberrypi:8080/handle?darknessSensor1in==1&lamp1out=1`. The answer would be `{"lamp1out":1}` if it was dark enough (and darknessSensor1in==1 is true) or `{}` if it is not dark enough (and darknessSensor1in==1 is false).

You could also check condition of another output port and react on that, e.g. `http://raspberrypi:8080/handle?otherOutputPort==0&lamp1out=1`.

You have to expect the following responses: 

Value | Meaning
:---: | --------
-3    | An analog input port has never been read (during process runtime).
-2    | An output pin is blocked and can not be set now.
-1    | A pin has no state (probably an error case).
empty | The key and value are missing. The port is not configured or the port is configured as input and was tryed to set (or vice versa) or a conditional port was not set.
0     | An output port was set to 0 or an input port currently returns 0.
1     | An output port was set to 1 or an input port currently returns 1.

#### Conditions

The following comparison operators are currently support:
```
==
!=
>
>=
<
<=
```

Watch out that your values for VIRTUAL ports must be numeric in order to use it for conditions or you get a NumberFormatException.

### Automatic Control

Imagine you want to turn on the lamp between 16:00 and 21:00 whenever it is dark enough and turn it off at 22:30. Remember that lamp1out has a "momentary contact switch" (Therefore we have to keep track if it is turned on or off and always set port 1 to turn it on or off).

Add the following lines to cron.conf:

`0 * 16-21 ? * * :: VIRTUALlamp1alreadyOn==0&darknessSensor1in==1&lamp1out=1&VIRTUALlamp1alreadyOn=1`

`0 30 22 ? * * :: VIRTUALlamp1alreadyOn==1&lamp1out=1&VIRTUALlamp1alreadyOn=0`

Every minute the virtual variable is checked VIRTUALlamp1alreadyOn. If lamp is not on, the darkness sensor darknessSensor1in is check. If both conditions are true, the lamp lamp1out is turned on and the state is changed. At 22:30, the lamp is turned off and the state is changed.

You can be creative here, e.g. if you want to recheck every 15 minutes if it is still dark enough (or if there was just a dark cloud), add the follwoing line:

`30 */15 16-21 ? * * :: VIRTUALlamp1alreadyOn==1&darknessSensor1in==0&lamp1out=1&VIRTUALlamp1alreadyOn=0`

Just to be sure check 30 seconds later to keep you out of concurrency trouble while setting/checking VIRTUALlamp1alreadyOn.

### Analog INPUT

A simple but powerful circuit can be found at [raspberrypi-spy.co.uk: Reading Analogue Sensors](http://www.raspberrypi-spy.co.uk/2012/08/reading-analogue-sensors-with-one-gpio-pin/) which makes analog inputs simple to read and handle in software.

**Please also read comments in gpio.conf about the exact internal processing.**

Although it is an analog input port, you must explicitly start reading the value (IN) because it may be slow (and blocks your port and your http request). The last read value is saved internally and can be used afterwards with conditions (initial and error value is -1). Keep in mind that reading may be slow. With manual control, your response may be slow (since reading blocks the port). With automatic control, make sure that the read process has finished or you may check against a previous value.

#### Example:

The following request will read a new value for analogSensor2ti (request is blocked until it is read), and will afterwards check if analogSensor2ti > 10000 and may set lamp1out.

`http://raspberrypi:8080/handle?analogSensor2ti=IN&analogSensor2ti>10000&lamp1out=1`

With the following two cronjobs you would set your lamp1out 15 minutes later than expected because reading take a little while and you check against an old value

`0 */15 16-21 ? * * :: analogSensor2ti=IN`

`0 */15 16-21 ? * * :: analogSensor2ti!=-1&analogSensor2ti>10000&lamp1out=1`

Given your analogSensor2ti takes 1200 milliseconds to be read at maximum, the following example is better:

`0 */15 16-21 ? * * :: analogSensor2ti=IN`

`3 */15 16-21 ? * * :: analogSensor2ti!=-1&analogSensor2ti>10000&lamp1out=1`

You can also do it all at once:

`0 */15 16-21 ? * * :: analogSensor2ti=IN&analogSensor2ti!=-1&analogSensor2ti>10000&lamp1out=1`

#### Please Note

The order of digital input ports and analog input ports is respected, but mixing output ports and input ports will change the internal processing (output ports are grouped and come last. Conditions break the groups into subgroups), e.g.

* `out1=1&analogTI=IN&out2=1` is handled internally as `analogTI=IN&out1=1&out2=1`

* `out1=1&in1=IN&out2=1&analogTI=IN&out3=1` is handled  internally as `in1=IN&analogTI=IN&out1=1&out2=1&out3=1`

* `out1=1&in1==1&out2=1&analogTI=IN&out3=1` (given in1==1 is true) is handled  internally as `out1=1&in1==1&analogTI=IN&out2=1&out3=1`


## Copyright

Copyright 2012  der-bub.de

http://www.der-bub.de

Authors: 
Sebastian Bub (sebastian@der-bub.de)


## License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.