Benutzer-Werkzeuge

Webseiten-Werkzeuge


pihome_basics_framework

Tutorial : Framework basis

Python anstatt Browser

Using WebIOPi from the browser is easy, but using it from an application is now easy as well. Just like the Javascript library, you can use the Python and Java Client libraries to make anything-to-Pi or Pi-to-Pi communication. Python client library provides both HTTP and CoAP WebIOPi Clients, and also a Mixed one, which uses CoAP with a HTTP fallback.

from webiopi.clients import *
from time import sleep

# Create a WebIOPi client
client = PiHttpClient("192.168.1.234")
#client = PiMixedClient("192.168.1.234")
#client = PiCoapClient("192.168.1.234")
#client = PiMulticastClient()

client.setCredentials("webiopi", "raspberry")

# RPi native GPIO
gpio = NativeGPIO(client)
gpio.setFunction(25, "out")
state = True

# DAC named "dac1"
dac = DAC(client, "dac1")

# ADC named "adc1"
adc = ADC(client, "adc1")
value = 0.0

# Temperature sensor named "temp0"
temp = Temperature(client, "temp0")

while True:
    # toggle digital state
    state = not state
    gpio.digitalWrite(25, state)

    # increase analog value
    value += 0.01
    if value > 1.0:
        value = 0.0
    dac.writeFloat(0, value)

    # DAC output 0 is wired to ADC input 1
    val = adc.readFloat(1)
    print("Analog = %.2f" % val)
    
    # Retrieve temperature
    t = temp.getCelsius()
    print("Temperature = %.2f Celsius" % t)

    sleep(1)

Light Control with auto on/off

Making an IoT application using WebIOPi is very easy once we catch how it works and what is necessary.

WebIOPi includes an HTTP server that provides both HTML resources and a REST API to control things. Your browser will first load a HTML file, then the included Javascript will make Asynchronous calls to the REST API to control and update the UI. This method is very efficient, because it don't need to refresh and download the whole page.

  You can build your HTML / Web UI from scratch, using the WebIOPi JS library or not.
  You can extend the WebIOPi behavior by loading custom Python script using an Arduino like syntax with setup/loop functions 

Assume we simply want a button to control a light, which will be automatically turned on and off. I say a light, but it can be a anything you want. The customization process has 3 steps :

  Write a simple Python script to initialize the GPIO and handle auto on/off
  Write a simple HTML/Javascript page
  Configure WebIOPi Server 

Prerequisites

  If not already done, install WebIOPi on your Raspberry Pi.
  Create a folder somewhere on your Pi, for instance /home/pi/myproject. This is the main folder.
  Create another python folder in the folder previously created. We will store Python script file here.
  Create another html folder next to python. We will store HTML and other ressources here. 

You should have something like this :

home - pi

  1. myproject
    1. python
    2. html

Python script

Create a script.py file in your python folder, eg. /home/pi/myproject/python/script.py. This file will be loaded and executed by the WebIOPi server.

import webiopi
import datetime

GPIO = webiopi.GPIO

LIGHT = 17 # GPIO pin using BCM numbering

HOUR_ON  = 8  # Turn Light ON at 08:00
HOUR_OFF = 18 # Turn Light OFF at 18:00

# setup function is automatically called at WebIOPi startup
def setup():
    # set the GPIO used by the light to output
    GPIO.setFunction(LIGHT, GPIO.OUT)

    # retrieve current datetime
    now = datetime.datetime.now()

    # test if we are between ON time and tun the light ON
    if ((now.hour >= HOUR_ON) and (now.hour < HOUR_OFF)):
        GPIO.digitalWrite(LIGHT, GPIO.HIGH)

# loop function is repeatedly called by WebIOPi 
def loop():
    # retrieve current datetime
    now = datetime.datetime.now()

    # toggle light ON all days at the correct time
    if ((now.hour == HOUR_ON) and (now.minute == 0) and (now.second == 0)):
        if (GPIO.digitalRead(LIGHT) == GPIO.LOW):
            GPIO.digitalWrite(LIGHT, GPIO.HIGH)

    # toggle light OFF
    if ((now.hour == HOUR_OFF) and (now.minute == 0) and (now.second == 0)):
        if (GPIO.digitalRead(LIGHT) == GPIO.HIGH):
            GPIO.digitalWrite(LIGHT, GPIO.LOW)

    # gives CPU some time before looping again
    webiopi.sleep(1)

# destroy function is called at WebIOPi shutdown
def destroy():
    GPIO.digitalWrite(LIGHT, GPIO.LOW)

That's it ! No HTTP boring stuff. The file will be loaded by the WebIOPi server which already handle remote control. HTML/Javascript

Create a index.html file in your html folder, eg. /home/pi/myproject/html/index.html. The WebIOPi Javascript library allows you to make your own interface easily with buttons bound to GPIO. You only need a single <script> tag to include /webiopi.js. It will then automatically load jQuery, a nice JS library.

You don't need to put webiopi.js and jquery.js in your project html folder. You just need the <script> tag in your index.html. The WebIOPi server filters browsers requests to serves both webiopi.js and jquery.js files from the default WebIOPi resource folder.

The index.html is composed of few HTML tags, including a little Javascript part and few CSS lines. The most important to take care about is the anonymous Javascript function passed to WebIOPi JS library with webiopi().ready(). This ensure WebIOPi and jQuery libraries are loaded before modifying the UI. Also take take of the parenthesis when prefixing functions calls with webiopi(). After the button creation, we use a jQuery function to append it to a HTML element, declared later in the <body> tag.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>WebIOPi | Light Control</title>
        <script type="text/javascript" src="/webiopi.js"></script>
        <script type="text/javascript">
        webiopi().ready(function() {
                // Create a "Light" labeled button for GPIO 17
                var button = webiopi().createGPIOButton(17, "Light");

                // Append button to HTML element with ID="controls" using jQuery
                $("#controls").append(button);

                // Refresh GPIO buttons
                // pass true to refresh repeatedly of false to refresh once
                webiopi().refreshGPIO(true);
        });
                
        </script>
        <style type="text/css">
                button {
                        display: block;
                        margin: 5px 5px 5px 5px;
                        width: 160px;
                        height: 45px;
                        font-size: 24pt;
                        font-weight: bold;
                        color: white;
                }
                
                #gpio17.LOW {
                        background-color: Black;
                }
                
                #gpio17.HIGH {
                        background-color: Blue;
                }
        </style>
</head>
<body>
        <div id="controls" align="center"></div>
</body>
</html>

Configuration

Edit /etc/webiopi/config :

    Locate [SCRIPTS] section, add following line to load your Python script

    ...
    [SCRIPTS]
    myproject = /home/pi/myproject/python/script.py
    ...

    Locate [HTTP] section, add following line to tell WebIOPi where to find your HTML resources

    ...
    [HTTP]
    doc-root = /home/pi/myproject/html
    ...

The two steps above are enough to run our app, but we want to limit remote control to the Light only. By default, we can remotely change function and value of all GPIO.

    Locate [REST] section, add following lines

    ...
    [REST]
    gpio-export = 17
    gpio-post-value = true
    gpio-post-function = false 
    ...

    gpio-export limits GPIO exported on the REST API (using BCM numbering)
    gpio-post-value allows/forbids to remotely change GPIO values (LOW/HIGH)
    gpio-post-function allows/forbids to remotely change GPIO function (IN/OUT) 

Testing

To debug your script and config, you should first run WebIOPi foreground before using the daemon service :

sudo webiopi -d -c /etc/webiopi/config

You can now open your browser to your Raspberry Pi IP at port 8000 (http://raspberrypi:8000/) and control a light/led connected to GPIO 17.

You can then follow the tutorial on macros to learn how to remotely change on and off hours.

Using Macros

Tutorial : Using macros Programmable Light control

Once we can control some light with automatic turn on/off, we may want to change the on/off hours from the UI. We can use webiopi macros to achieve it. Macros are custom Pythons functions automatically bound to the REST API, so they are remotely callable. They allow to remotely trigger complex computation on the Raspberry Pi or manual events, trigger multiple GPIO at the same time, change settings… Adding macro in the Python script

Registering macros to the WebIOPi server only requires a single Python decorator before each function. From the Framework Basis Tutorial, edit and update the Python script file, eg. /home/pi/myproject/python/script.py.

import webiopi
...
HOUR_ON = 8
HOUR_OFF = 18
...
def setup():
...
def loop():
...
def destroy():
...

@webiopi.macro
def getLightHours():
    return "%d;%d" % (HOUR_ON, HOUR_OFF)

@webiopi.macro
def setLightHours(on, off):
    global HOUR_ON, HOUR_OFF
    HOUR_ON = int(on)
    HOUR_OFF = int(off)
    return getLightHours()

Both get/setLightHours functions are declared to WebIOPi using the @webiopi.macro decorator. The first one return a string containing both ON and OFF hours separated by a semicolon. The second function casts arguments received and set ON and OFF hours as well as returning the effective hours to give a feedback to the remote UI.

Using Devices

Tutorial : Using devices Programmable Heater with Temperature Sensor and GPIO Expander

WebIOPi include several drivers to directly control over 30 electronic devices. It provides a consistent and common abstraction for most used sensors, analog converters, and GPIO expanders. See the supported devices pages for a complete listing.

All supported devices can be used in your Python script, from the REST API, the Javascript library, or even from the Python or Java Client. Function provided depend on the devices type. Devices can support one or multiples interfaces. Interfaces are grouped in 3 packages :

  Digital
      GPIOPort (I/O Expanders) 
  Analog
      ADC (Analog to Digital Converter, ie. analog inputs)
      DAC (Digital to Analog Converter, ie. analog outputs)
      PWM (Pulse Width Modulation outputs) 
  Sensor
      Temperature
      Pressure
      Luminosity
      Distance 

Prerequisites

  WebIOPi installed on your Raspberry
      Follow Install Tutorial 
  Know WebIOPi framework basis, and how to launch WebIOPi foreground (debug)
      Follow Framework Basis Tutorial 
  Know how to write and use macros
      Follow Using Macros Tutorial 
  A supported Temperature sensor
  A supported GPIO expander
  Know how to wire components on the Raspberry Pi
      Google about it. There is plenty example on Internet. 
  Check Hacker Tips 

Testing Devices

Before using devices in your Pythons script or custom UI, you may need to debug your circuitry and at least, verify it works well with the WebIOPi environment. You don't need to write any line of code to test your devices, thanks to the WebIOPi configuration file.

WebIOPi handles by itself linux modules loading to support I2C, SPI, and 1-Wire. But it only works if you do not use any other GPIO library. I suggest to reboot your Pi at this time.

Edit /etc/webiopi/config.

Assume we have a TMP102 I2C Temperature sensor, simply add following line in the [DEVICES] section to register it with the name tmp. This name will be used to identify the sensor in the whole system. I say a TMP102, but it can be any Temperature sensor supported by WebIOPi. Except from the config syntax, they all have the same functions.

[DEVICES] tmp = TMP102

Assume we also have a MCP23017 I2C GPIO Expander, then we can also add the optional I2C slave address. Again, I say a MCP23017, but it can be any GPIO expander supported. Just adapt the config line to your chipset, the rest of the tutorial remains unchanged.

[DEVICES] tmp = TMP102 mcp = MCP23017 slave:0x20

Ensure you don't have any doc-root directive in the [HTTP] section to use defaults web apps, save, and restart webiopi to use the device monitor (http://raspberrypi:8000/app/devices-monitor/).

Devices in Python scripts with REST mapping

When devices are named in the configuration file, drivers are automatically called to initialize the device and mapped to the REST API. We need to use the webiopi.deviceInstance(name) function in the Python script to retrieve the device object instance for the given name. Then we can use functions of the drivers, depending of interfaces supported. You will find a link to all interfaces supported with a complete function list on the top of each device wiki pages. See TMP102 and MCP230xx for instance.

The following example automatically turns on/off the heater, plugged on a GPIO expander, depending on the temperature given by a the sensor. There is also a main AUTO flag to allow forcing the heater.

import webiopi
GPIO = webiopi.GPIO # Helper for LOW/HIGH values
HEATER = 7 # Heater plugged on the Expander Pin 7
MIN = 22 # Minimum temperature in celsius
MAX = 24 # Maximum temperature in celsius
AUTO = True

# setup function is automatically called at WebIOPi startup
def setup():
    mcp = webiopi.deviceInstance("mcp") # retrieve the device named "mcp" in the configuration 
    mcp.setFunction(HEATER, GPIO.OUT)

# loop function is repeatedly called by WebIOPi 
def loop():
    if (AUTO):
        tmp = webiopi.deviceInstance("tmp") # retrieve the device named "tmp" in the configuration
        mcp = webiopi.deviceInstance("mcp") # retrieve the device named "mcp" in the configuration 

        celsius = tmp.getCelsius() # retrieve current temperature
        print("Temperature: %f" % celsius)

        # Turn ON heater when passing below the minimum temperature
        if (celsius < MIN):
            mcp.digitalWrite(HEATER, GPIO.HIGH)

        # Turn OFF heater when reaching maximum temperature
        if (celsius >= MAX):
            mcp.digitalWrite(HEATER, GPIO.LOW)

    # gives CPU some time before looping again
    webiopi.sleep(1)

# destroy function is called at WebIOPi shutdown
def destroy():
    mcp = webiopi.deviceInstance("mcp") # retrieve the device named "mcp" in the configuration 
    mcp.digitalWrite(HEATER, GPIO.LOW) # turn off to avoid over heating

# a simple macro to return heater mode
@webiopi.macro
def getMode():
    if (AUTO):
        return "auto"
    return "manual"

# simple macro to set and return heater mode
@webiopi.macro
def setMode(mode):
    global AUTO
    if (mode == "auto"):
        AUTO = True
    elif (mode == "manual"):
        AUTO = False
    return getMode()

Using Serials

pihome_basics_framework.txt · Zuletzt geändert: von 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki