Using the OLinuXino Micro and a USB 3G modem to control something via web

OlinuXino Micro with a USB 3G modem
Overview
First you need a working internet connection on the OLinuXino, either via WiFi or Ethernet to install some tools. In my previous blog post there is an example how to configure a kernel with WiFi and USB 3G modem support and how to set up an internet connection on the OLinuXino.
Update: The default Arch Linux ARM image now has proper WiFi and USB 3G modem support (A new SD card image for the iMX233-OLinuXino), building your own kernel is not longer necessary.
Set up an internet connection
Connect an USB WiFi adapter and set up a network connection:
[root@alarm ~]#
[ 858.720000] usb 1-1: new high-speed USB device number 3 using ci_hdrc
[ 858.880000] usb 1-1: ath9k_htc: Firmware htc_7010.fw requested
[ 859.200000] usb 1-1: ath9k_htc: Transferred FW: htc_7010.fw, size: 72992
[ 859.260000] ath9k_htc 1-1:1.0: ath9k_htc: HTC initialized with 45 credits
[ 859.680000] ath9k_htc 1-1:1.0: ath9k_htc: FW Version: 1.3
[ 859.760000] ieee80211 phy0: Atheros AR9287 Rev:2
[root@alarm ~]# ifconfig wlan0 down
[root@alarm ~]# iwconfig wlan0 mode ad-hoc
[root@alarm ~]# iwconfig wlan0 channel 4
[root@alarm ~]# iwconfig wlan0 essid tuxnet
[root@alarm ~]# iwconfig wlan0 key 73598253812539275395295235
[root@alarm ~]# ifconfig wlan0 up
[ 1143.570000] wlan0: Selected IBSS BSSID a2:1c:4f:5c:ef:c4 based on configured SSID
[root@alarm ~]# dhcpcd wlan0
dhcpcd[256]: version 5.5.6 starting
dhcpcd[256]: all: not configured to accept IPv6 RAs
dhcpcd[256]: wlan0: rebinding lease of 10.42.0.48
dhcpcd[256]: wlan0: broadcasting for a lease
dhcpcd[256]: wlan0: offered 10.42.0.48 from 10.42.0.1
dhcpcd[256]: wlan0: acknowledged 10.42.0.48 from 10.42.0.1
dhcpcd[256]: wlan0: checking for 10.42.0.48
dhcpcd[256]: wlan0: leased 10.42.0.48 for 3600 seconds
dhcpcd[256]: forked to background, child pid 282
[root@alarm ~]# ping google.de
PING google.de (74.125.230.248) 56(84) bytes of data.
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=1 ttl=53 time=385 ms
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=2 ttl=53 time=314 ms
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=3 ttl=53 time=333 ms
--- google.de ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 314.719/344.448/385.125/29.767 ms
[root@alarm ~]#
Install usb_modeswitch and wvdial
We use the pacman package manager to install some tools:
[root@alarm ~]# pacman -Sy
:: Synchronizing package databases...
core 38.3 KiB 89.5K/s 00:00 [######################] 100%
extra 434.8 KiB 7.17K/s 01:01 [######################] 100%
community 438.6 KiB 7.35K/s 01:00 [######################] 100%
alarm 4.9 KiB 166K/s 00:00 [######################] 100%
aur 12.2 KiB 71.6K/s 00:00 [######################] 100%
[root@alarm ~]# pacman -S usb_modeswitch wvdial vim
resolving dependencies...
looking for inter-conflicts...
Targets (5): tcl-8.5.13-1 wvstreams-4.6.1-5 xplc-0.3.13-4
usb_modeswitch-1.2.5-1 wvdial-1.61-4
Total Download Size: 0.75 MiB
Total Installed Size: 15.04 MiB
Proceed with installation? [Y/n] Y
:: Retrieving packages from community...
wvstreams-4.6.1-5-arm 1032.6 KiB 8.64K/s 02:00 [######################] 100%
wvdial-1.61-4-arm 57.2 KiB 8.47K/s 00:07 [######################] 100%
(5/5) checking package integrity [######################] 100%
(5/5) loading package files [######################] 100%
(5/5) checking for file conflicts [######################] 100%
(5/5) checking available disk space [######################] 100%
(1/5) installing tcl [######################] 100%
(2/5) installing usb_modeswitch [######################] 100%
(3/5) installing xplc [######################] 100%
(4/5) installing wvstreams [######################] 100%
(5/5) installing wvdial [######################] 100%
[root@alarm ~]#
Note
I have also updated all packages pacman -Syu and enabled systemd as default init system but this is not necessary to run the webapp, there are some manual changes necessary, see also https://wiki.archlinux.org/index.php/Systemd. You can check if systemd is currently active by using the following command: cat /proc/1/comm. This should return the string systemd and $ cat /proc/cmdline should return noinitrd console=ttyAMA0,115200 root=/dev/mmcblk0p2 init=/usr/lib/systemd/systemd rw rootwait ssp1=mmc.
To get rid of some warnings:
HOSTNAME= is deprecated. See rc.conf(5) and hostname(5) for details.
HARDWARECLOCK= is deprecated. See rc.conf(5) and hwclock(8) for details.
TIMEZONE= is deprecated. See rc.conf(5) for details.
Comment out some lines in /etc/rc.conf:
#LOCALE="en_US.UTF-8"
#HARDWARECLOCK="UTC"
#TIMEZONE="America/Chicago"
#KEYMAP="us"
#HOSTNAME="alarm"
And execute the following commands:
[root@alarm ~]# echo LANG=en_US.UTF-8 > /etc/locale.conf
[root@alarm ~]# echo Europe/Berlin > /etc/timezone
[root@alarm ~]# rm /etc/localtime
[root@alarm ~]# ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime
[root@alarm ~]# echo KEYMAP=us > /etc/vconsole.conf
Connect and configure the USB 3G modem
How to setup a USB 3G Modem under Arch Linux is explained in the ArchWiki: https://wiki.archlinux.org/index.php/USB_3G_Modem.
Now disable WiFi, disconnect your WiFi adapter and plug in the 3G modem:
[root@alarm ~]# ifconfig wlan0 down
[root@alarm ~]#
[ 2776.880000] usb 1-1: USB disconnect, device number 3
[ 2776.960000] usb 1-1: ath9k_htc: USB layer deinitialized
[ 162.480000] usb 1-1: new high-speed USB device number 2 using ci_hdrc
[ 162.660000] scsi0 : usb-storage 1-1:1.0
[ 163.700000] scsi 0:0:0:0: CD-ROM USBModem Disk 2.31 PQ: 0 ANSI: 2
[ 165.490000] usb 1-1: USB disconnect, device number 2
[ 165.890000] usb 1-1: new high-speed USB device number 3 using ci_hdrc
[ 166.070000] option 1-1:1.0: GSM modem (1-port) converter detected
[ 166.090000] usb 1-1: GSM modem (1-port) converter now attached to ttyUSB0
[ 166.100000] option 1-1:1.1: GSM modem (1-port) converter detected
[ 166.120000] usb 1-1: GSM modem (1-port) converter now attached to ttyUSB1
[ 166.130000] option 1-1:1.2: GSM modem (1-port) converter detected
[ 166.150000] usb 1-1: GSM modem (1-port) converter now attached to ttyUSB2
[ 166.160000] scsi1 : usb-storage 1-1:1.3
[ 167.170000] scsi 1:0:0:0: Direct-Access USBModem Disk 2.31 PQ: 0 ANSI: 2
[ 167.400000] sd 1:0:0:0: [sda] Attached SCSI removable disk
[root@alarm ~]# lsusb
Bus 001 Device 005: ID 1c9e:9603 OMEGA TECHNOLOGY
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
We use wvdial to connect via UMTS to the internet.
You need to create the configuration file /etc/wvdial.conf, just google for wvdial.conf and the name of your USB 3G modem and you will likely find a working configuration, mine looks like this:
[root@alarm ~]# vim /etc/wvdial.conf
[root@alarm ~]# cat /etc/wvdial.conf
[Dialer Defaults]
Phone = *99#
Username = "blau"
Password = "blau"
Stupid Mode = on
Dial Command = ATDT
Modem Type = USB Modem
Modem = /dev/ttyUSB2
Init1 = ATZ
[Dialer nopin]
Init2= AT+CPIN="1234"
Init3= AT+CLCK="SC",0,"1234"
[Dialer umts]
Carrier Check = on
Init2= AT+CGDCONT?
Init3= AT+CGDCONT=1,"IP","internet.eplus.de"
ISDN = off
[root@alarm ~]#
Once the configuration files are prepared, the internet connection is established by running:
[root@alarm ~]# wvdial umts &
[1] 304
--> WvDial: Internet dialer version 1.61
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: AT+CGDCONT=1,"IP","internet.eplus.de"
AT+CGDCONT=1,"IP","internet.eplus.de"
OK
--> Modem initialized.
--> Sending: ATDT*99#
--> Waiting for carrier.
ATDT*99#
CONNECT 7200000
--> Carrier detected. Starting PPP immediately.
--> Starting pppd at Wed Dec 31 18:34:43 1969
--> Pid of pppd: 305
--> Using interface ppp0
--> pppd: ??6
--> pppd: ??6
--> pppd: ??6
--> pppd: ??6
--> pppd: ??6
--> pppd: ??6
--> pppd: ??6
--> local IP address 10.120.143.161
--> pppd: ??6
--> remote IP address 10.64.64.64
--> pppd: ??6
--> primary DNS address 212.23.115.148
--> pppd: ??6
--> secondary DNS address 212.23.97.2
--> pppd: ??6
[root@alarm ~]# ping google.de
PING google.de (74.125.230.248) 56(84) bytes of data.
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=1 ttl=54 time=363 ms
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=2 ttl=54 time=332 ms
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=3 ttl=54 time=312 ms
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=4 ttl=54 time=332 ms
--- google.de ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 312.688/335.242/363.438/18.173 ms
[root@alarm ~]#
Sometimes it could be necessary to manually add a nameserver to /etc/resolf.conf:
[root@alarm ~]# echo 'nameserver 208.67.222.222' | tee -a /etc/resolv.conf
Get a public IP address with PageKite
The main problem with mobile internet is that if you connect through a 3G USB dongle you don’t have a public IP address but one behind a NAT gateway that is not accessible from the internet.
So theoretically you can’t run a web server via UMTS but luckily there exists a little Open Source Python script called PageKite to overcome this problem.
Install PageKite on the OLinuXino
The QuickStart Guide: https://pagekite.net/support/quickstart/
[root@alarm ~]# wget http://pagekite.net/pk/pagekite.py
--1969-12-31 19:28:26-- http://pagekite.net/pk/pagekite.py
Resolving pagekite.net (pagekite.net)... 69.164.211.158
Connecting to pagekite.net (pagekite.net)|69.164.211.158|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 160192 (156K) [text/x-python]
Saving to: `pagekite.py'
100%[======================================>] 160,192 11.2K/s in 14s
1969-12-31 19:28:43 (11.2 KB/s) - `pagekite.py' saved [160192/160192]
[root@alarm ~]# python pagekite.py --signup
-bash: python: command not found
[root@alarm ~]# pacman -S python
resolving dependencies...
looking for inter-conflicts...
Targets (1): python-3.3.0-2
Total Download Size: 11.39 MiB
Total Installed Size: 90.20 MiB
Proceed with installation? [Y/n] y
:: Retrieving packages from extra...
python-3.3.0-2-arm 11.4 MiB 6.76K/s 28:47 [######################] 100%
(1/1) checking package integrity [######################] 100%
(1/1) loading package files [######################] 100%
(1/1) checking for file conflicts [######################] 100%
(1/1) checking available disk space [######################] 100%
(1/1) installing python [######################] 100%
Optional dependencies for python
tk: for tkinter
sqlite
[root@alarm ~]#
[root@alarm ~]# python pagekite.py --signup
File "pagekite.py", line 242
exec __FILES[".SELF/sockschain/__init__.py"] in sys.modules["sockschain"].__dict__
^
SyntaxError: invalid syntax
[root@alarm ~]# # fuck we need python2
[root@alarm ~]# pacman -S python2
resolving dependencies...
looking for inter-conflicts...
Targets (2): sqlite-3.7.14.1-1 python2-2.7.3-3
Total Download Size: 8.61 MiB
Total Installed Size: 68.77 MiB
Proceed with installation? [Y/n] y
:: Retrieving packages from extra...
python2-2.7.3-3-arm 8.6 MiB 6.78K/s 21:41 [######################] 100%
(2/2) checking package integrity [######################] 100%
(2/2) loading package files [######################] 100%
(2/2) checking for file conflicts [######################] 100%
(2/2) checking available disk space [######################] 100%
(1/2) installing sqlite [######################] 100%
(2/2) installing python2 [######################] 100%
Optional dependencies for python2
tk: for IDLE
[root@alarm ~]# python2 pagekite.py --signup
[root@alarm ~]# python2 pagekite.py 80 olinuxino.pagekite.me
>>> Hello! This is pagekite.py v0.5.4a. [CTRL+C = Stop]
!!! Failed to connect to 178.79.140.143:443
!!! Failed to connect to 69.164.211.158:443
!!! Failed to connect to 93.95.226.149:443
<< pagekite.py [down] Not connected to any front-ends, will retry...
It seems there is a problem with openssl on the OLinuXino:
[root@alarm ~]# curl -s https://pagekite.net/pk
[root@alarm ~]# curl http://pagekite.net/pk
exec curl -s -L -k https://pagekite.net/pk/ |bash #
[root@alarm ~]# curl -v -s https://pagekite.net/pk
* About to connect() to pagekite.net port 443 (#0)
* Trying 69.164.211.158...
* connected
* Connected to pagekite.net (69.164.211.158) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem: certificate is not yet valid
* Closing connection #0
[root@alarm ~]#
And there is the problem: certificate is not yet valid. Not yet?
We nee to set the correct date: https://wiki.archlinux.org/index.php/Network_Time_Protocol_daemon.
Update
It seems Arch Linux ARM installs now openntpd instead of ntp by default, use man ntdp to find the correct commandline option.
[root@alarm ~]# pacman -S ntp
resolving dependencies...
looking for inter-conflicts...
Targets (1): ntp-4.2.6.p5-12
Total Download Size: 0.39 MiB
Total Installed Size: 1.49 MiB
Proceed with installation? [Y/n] y
:: Retrieving packages from extra...
ntp-4.2.6.p5-12-arm 395.2 KiB 7.90K/s 00:50 [######################] 100%
(1/1) checking package integrity [######################] 100%
(1/1) loading package files [######################] 100%
(1/1) checking for file conflicts [######################] 100%
(1/1) checking available disk space [######################] 100%
(1/1) installing ntp [######################] 100%
[root@alarm ~]# systemctl enable ntpd.service
ln -s '/usr/lib/systemd/system/ntpd.service' '/etc/systemd/system/multi-user.target.wants/ntpd.service'
[root@alarm ~]# ntpd -qg
ntpd: time set +1355695847.651911s
[root@alarm ~]# systemctl start ntpd.service
[root@alarm ~]# curl -s https://pagekite.net/pk
exec curl -s -L -k https://pagekite.net/pk/ |bash #
[root@alarm ~]#
Test if the OLinuXino is accessible via web
[root@alarm ~]# mkdir www
[root@alarm ~]# vim www/index.html
[root@alarm ~]# cat www/index.html
Hello World!
[root@alarm ~]# python2 pagekite.py www olinuxino.pagekite.me
>>> Hello! This is pagekite.py v0.5.4a. [CTRL+C = Stop]
Connecting to front-end 69.164.211.158:443 ...
- Protocols: http http2 http3 https websocket irc finger httpfinger raw
- Ports: 79 80 443 843 2222 3000 4545 5222 5223 5269 5670 6667 8000 8080
- Ports: 8081 9292
- Raw ports: 22 virtual
Quota: You have 2560.00 MB, 31 days and 5 connections left.
~<> Flying builtin HTTPD as https://olinuxino.pagekite.me/
- https://olinuxino.pagekite.me/
46.115.59.235 < http://olinuxino.pagekite.me:80 (builtin)
<< pagekite.py [flying] Kites are flying and all is well.
SSH into the OLinuXino from everywhere
Warning: Make sure to change the default root password.
[root@alarm ~]# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
[root@alarm ~]#
Start a simple www server for the www directory and also redirect port 22 for incoming ssh connections:
[root@alarm ~]# python2 pagekite.py www olinuxino.pagekite.me AND 22 ssh:olinuxino.pagekite.me
>>> Hello! This is pagekite.py v0.5.4a. [CTRL+C = Stop]
Connecting to front-end 178.79.140.143:443 ...
- Protocols: http http2 http3 https websocket irc finger httpfinger raw
- Ports: 79 80 443 843 2222 3000 4545 5222 5223 5269 5670 6667 8000 8080
- Ports: 8081 9292
- Raw ports: 22 virtual
Quota: You have 2560.00 MB, 31 days and 5 connections left.
~<> Flying localhost:22 as ssh://olinuxino.pagekite.me:22/ (HTTP proxied)
~<> Flying builtin HTTPD as https://olinuxino.pagekite.me/
- https://olinuxino.pagekite.me/
Connecting to front-end 69.164.211.158:443 ...
<< pagekite.py [flying] Kites are flying and all is well.
[root@alarm ~]#
If you get the error ssh_exchange_identification: Connection closed by remote host, then the solution as written here and there is to edit your ~/.ssh/config on your PC and add the following:
Host *.pagekite.me
CheckHostIP no
ProxyCommand /bin/nc -X connect -x %h:443 %h %p
A simple Python webapp to control some LEDs
Used software
- http://flask.pocoo.org/
- https://github.com/mbr/flask-bootstrap/
- https://github.com/twbs/bootstrap
- https://pagekite.net/
- https://github.com/christianjann/olinuxino-webcontrol-minimal
Install everything:
[root@alarm ~]# pacman -S python2-flask python2-pip git
[root@alarm ~]# pip2 install flask-bootstrap
[root@alarm ~]# git clone https://github.com/christianjann/olinuxino-webcontrol-minimal.git webcontrol
Cloning into 'webcontrol'...
remote: Counting objects: 12, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 12 (delta 2), reused 12 (delta 2)
Unpacking objects: 100% (12/12), done.
[root@alarm ~]#
Test it
Try some functions on the interactive python command prompt:
[root@alarm ~]# cd webcontrol
[root@alarm webcontrol]# python2
Python 2.7.3 (default, Dec 14 2012, 13:39:40)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from leds import *
>>> ledon()
>>> ledoff()
>>> ledon()
>>> ledheartbeat()
>>> export_pins(32)
>>> setpindirection(32, "out");
>>> writepins(32, 1)
>>> writepins(32, 0)
>>>
[root@alarm webcontrol]#
Start the webapp
With the help of GNU Screen ([root@alarm ~]# man screen) you can open several terminals at once on the OLinuXino:
- http://www.rackaid.com/resources/linux-screen-tutorial-and-how-to/
- http://www.gnu.org/software/screen/manual/screen.html
[chris@thinkpad ~]$ screen /dev/ttyUSB0 115200
[root@alarm ~]# pacman -S screen
[root@alarm ~]# screen
Now you can use the following key combinations to create new virtual terminals and switch between them:
- “Ctrl-a” “a” “c” for a new virtual terminal
- “Ctrl-a” “a” “n” for the next window
- “Ctrl-a” “a” “p” for the previous window
- “Ctrl-a” “a” “k” Kill, destroy the current window.
- “Ctrl-a” “d” to detach screen from the current terminal, screen -ls to list terminal sessions and screen -r to attach to one of them.
Virtual terminal 1: wvdial
[root@alarm ~]# wvdial umts
--> WvDial: Internet dialer version 1.61
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: AT+CGDCONT=1,"IP","internet.eplus.de"
AT+CGDCONT=1,"IP","internet.eplus.de"
OK
--> Modem initialized.
--> Sending: ATDT*99#
--> Waiting for carrier.
ATDT*99#
CONNECT 7200000
--> Carrier detected. Starting PPP immediately.
--> Starting pppd at Wed Dec 31 19:03:37 1969
--> Pid of pppd: 780
--> Using interface ppp0
--> pppd: ?i?[01]
--> pppd: ?i?[01]
--> pppd: ?i?[01]
--> pppd: ?i?[01]
--> pppd: ?i?[01]
--> pppd: ?i?[01]
--> pppd: ?i?[01]
--> local IP address 10.113.211.24
--> pppd: ?i?[01]
--> remote IP address 10.64.64.64
--> pppd: ?i?[01]
--> primary DNS address 212.23.115.148
--> pppd: ?i?[01]
--> secondary DNS address 212.23.97.2
--> pppd: ?i?[01]
Virtual terminal 2: app.py
[root@alarm ~]# cd webcontrol
[root@alarm webcontrol]# python2 app.py
The value on the PIN 32 is : 0
The value on the PIN 33 is : 0
* Running on http://127.0.0.1:5000/
* Restarting with reloader
GPIO 32 already Exists, so skipping export gpio
GPIO 33 already Exists, so skipping export gpio
The value on the PIN 32 is : 0
The value on the PIN 33 is : 0
127.0.0.1 - - [17/Dec/2012 04:46:42] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [17/Dec/2012 04:46:50] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [17/Dec/2012 04:47:43] "POST / HTTP/1.1" 200 -
127.0.0.1 - - [17/Dec/2012 04:47:44] "GET /favicon.ico HTTP/1.1" 404 -
Virtual terminal 3: pagekite
[root@alarm ~]# python2 pagekite.py 5000 olinuxino.pagekite.me:80
>>> Hello! This is pagekite.py v0.5.4a. [CTRL+C = Stop]
!!! Failed to connect to 178.79.140.143:443
!!! Failed to connect to 93.95.226.149:443
<< pagekite.py [down] Not connected to any front-ends, will retry...
[root@alarm ~]# ntpd -qg
ntpd: time set +1355736876.515633s
[root@alarm ~]# python2 pagekite.py 5000 olinuxino.pagekite.me:80
>>> Hello! This is pagekite.py v0.5.4a. [CTRL+C = Stop]
Connecting to front-end 178.79.140.143:443 ...
- Protocols: http http2 http3 https websocket irc finger httpfinger raw
- Ports: 79 80 443 843 2222 3000 4545 5222 5223 5269 5670 6667 8000 8080
- Ports: 8081 9292
- Raw ports: 22 virtual
Quota: You have 2559.67 MB, 30 days and 5 connections left.
Connecting to front-end 93.95.226.149:443 ...
~<> Flying localhost:5000 as https://olinuxino.pagekite.me:80/
<< pagekite.py [flying] Kites are flying and all is well.
The Source Code
app.py:
#!/usr/bin/env python
# coding=utf8
from flask import Flask, render_template, flash, request, redirect, url_for
from flask.ext.bootstrap import Bootstrap
from leds import *
# init gpio's
export_pins(32)
setpindirection(32, "out")
export_pins(33)
setpindirection(33, "out")
app = Flask(__name__)
Bootstrap(app)
app.config['BOOTSTRAP_USE_MINIFIED'] = True
app.config['BOOTSTRAP_USE_CDN'] = True
app.config['BOOTSTRAP_FONTAWESOME'] = True
app.config['SECRET_KEY'] = 'devkey'
@app.route('/')
def index():
in_out = {'led1': bool(readpins(32)), 'led2': bool(readpins(33))}
return render_template('example.html', in_out=in_out)
@app.route('/set_leds', methods=('GET', 'POST',))
def set_leds():
if request.method == 'POST':
led1 = bool(request.form.get('led1'))
led2 = bool(request.form.get('led2'))
print("led1: ", led1)
print("led2: ", led2)
flash('LEDs have been updated: LED1="' + str(led1)
+ '", LED2="' + str(led2) + '"', 'success')
writepins(32, int(led1))
writepins(33, int(led2))
return redirect(url_for('index'))
if __name__ == '__main__':
# '0.0.0.0': listen on all public IPs
app.run(host='0.0.0.0', port=5000, debug=True)
leds.py:
#!/usr/bin/env python
# coding=utf8
def ledon():
try:
value = open("/sys/class/leds/green/brightness", "w")
value.write(str(1))
value.close()
except:
print("ERR: ledon()")
def ledoff():
try:
value = open("/sys/class/leds/green/brightness", "w")
value.write(str(0))
value.close()
except:
print("ERR: ledoff()")
def ledheartbeat():
try:
value = open("/sys/class/leds/green/trigger", "w")
value.write("heartbeat")
value.close()
except:
print("ERR: ledheartbeat()")
def export_pins(pins):
try:
f = open("/sys/class/gpio/export", "w")
f.write(str(pins))
f.close()
except IOError:
print(
"GPIO %s already Exists, so skipping export gpio" % (str(pins), ))
except:
print("ERR: export_pins()")
def unexport_pins(pins):
try:
f = open("/sys/class/gpio/unexport", "w")
f.write(str(pins))
f.close()
except IOError:
print(
"GPIO %s is not found, so skipping unexport gpio" % (str(pins), ))
except:
print("ERR: unexport_pins()")
def setpindirection(pin_no, pin_direction):
try:
gpiopin = "gpio%s" % (str(pin_no), )
pin = open("/sys/class/gpio/" + gpiopin + "/direction", "w")
pin.write(pin_direction)
pin.close()
except:
print("ERR: setpindirection()")
def writepins(pin_no, pin_value):
try:
gpiopin = "gpio%s" % (str(pin_no), )
pin = open("/sys/class/gpio/" + gpiopin + "/value", "w")
if pin_value == 1:
pin.write("1")
else:
pin.write("0")
pin.close()
except:
print("ERR: writepins()")
def readpins(pin_no):
try:
gpiopin = "gpio%s" % (str(pin_no), )
pin = open("/sys/class/gpio/" + gpiopin + "/value", "r")
value = pin.read()
print("The value on the PIN %s is : %s" % (str(pin_no), str(value)))
pin.close()
return int(value)
except:
print("ERR: readpins()")
if __name__ == '__main__':
from time import sleep
export_pins(32)
setpindirection(32, "out")
while(1):
ledon()
writepins(32, 1)
sleep(1)
ledoff()
writepins(32, 0)
sleep(1)
example.html:
Based on https://github.com/twbs/bootstrap/tree/master/docs/examples/jumbotron and https://github.com/mbr/flask-bootstrap/tree/master/sample_application/templates.
{% extends "bootstrap/base.html" %}
{% macro check_box(name, text, value='', checked=False) -%}
{% if checked %}
<label class="checkbox"><input id="{{ name }}"
name="{{ name }}" type="checkbox"
value="{{ value|e}}" checked="checked"/>{{ text }}</label>
{% else %}
<label class="checkbox"><input id="{{ name }}"
name="{{ name }}" type="checkbox"
value="{{ value|e}}" />{{ text }}</label>
{% endif %}
{%- endmacro %}
{% block content %}
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<h1>Hello, world!</h1>
<p>This is a simple webapp running on the OLinuXino.
Use it as a starting point to create something more unique.</p>
<p><a href="http://www.jann.cc/2012/12/16/http://www.jann.cc/2012/12/16/olinuxino_micro_usb_3g_modem_web_control.html" class="btn btn-primary btn-lg" role="button">Learn more »</a></p>
</div>
</div>
<div class="container">
<!-- Example row of columns -->
<div class="row">
<div class="col-md-4">
<h2>LEDs</h2>
<form class="form form-horizontal" method="post"
action="{{ url_for('set_leds') }}">
<p>
{{ check_box('led1', 'LED 1', value='1', checked=in_out['led1']) }}
{{ check_box('led2', 'LED 2', value='1', checked=in_out['led2']) }}
</p>
<p><button name="action_save" type="submit"
class="btn btn-primary">Send new LED state</button></p>
</form>
</div>
<div class="col-md-4">
<h2>Heading</h2>
<p>Donec id elit non mi porta gravida at eget metus.</p>
<p><a class="btn btn-default" href="#" role="button">
View details »
</a></p>
</div>
<div class="col-md-4">
<h2>Heading</h2>
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in,
egestas eget quam.</p>
<p><a class="btn btn-default" href="#" role="button">
View details »</a></p>
</div>
</div>
<div class="row">
<div class="col-md-12">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} fade in">
<a href="#" data-dismiss="alert" class="close">×</a>
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
</div>
<hr>
<footer>
<p>© 2013 <a href="http://www.jann.cc">jann.cc</a></p>
</footer>
</div> <!-- /container -->
{% endblock %}
Now it’s up to you, put everything in a script and add it to /etc/rc.local so that it runs automatically at boot.
References/Further Reading
- https://wiki.archlinux.org/index.php/Pacman_Rosetta
- http://twitter.github.com/bootstrap/index.html
- https://code.google.com/p/raspberry-gpio-python/
- http://elinux.org/RPi_Low-level_peripherals
- http://echorand.me/2012/10/13/web-based-ssh-access-to-your-raspberry-pi/, https://github.com/aluzzardi/wssh
- https://blaisejarrett.com/projects/piio/
Pingback:
Last updated: 2013-10-17