This is a example project how to use Steelsquid Kiss OS to control a 10 LED bar, two buttons and the built in WEB-server...
If you do this you have learn a lot how to work with Steelsquid Kiss OS.

This is what i want to manage.
- Press the upper button to light one more LED until all lights.
- Press the lower button to decrease the number of glowing LEDs.
- The bottom LED should never be extinguished when you push down button.
- I also want a simple WEB interface that also can control the LED bar in the same way.
- And finally all LEDs should illuminate on network connected.
- And no LED lit on network disconnect.
- Flash all LEDs when there is a file in the /root directory named flash.
And then delete that file.
- Remember number of lit LEDs from last time
- And a parameter that say if Steelsquid Kiss OS is to enable all this
Dependencies on your development computer
For the synchronization script, SSH and GIT to works on Linux (preferably Debian) you need this packages installed.
It should work on any other Linux distribution also.
It probably works on Mac OS X also.
- gzip
- git
- openssh-client
- python2.7
- paramiko
apt-get install bash gzip git openssh-client python2.7 python-paramiko
For synchronization use the EXE-file: steelsquid_synchronize.exe
Install Steelsquid KISS OS on the Raspberry PI
Change directory to the project home on your development computer
- Insert sd-card into the Raspberry Pi and power it on
The IP of the Raspberry PI will be printed on the screen
Get the source code
On your development computer.
Change directory to where you want the source code (a project folder will be created)
git clone https://github.com/steelsquid/steelsquid-kiss-os.git
You can also download a zip here: Download this zip file and extract
Start the synchronisation between Raspberry and development computer
Go the the ROOT where you downloaded the source and edit config.txt
Should look like this, except the IP number that you must change to your Raspberry Pi IP. (For more info see this)
192.168.0.194
22
root
raspberry
Then execute: ./steelsquid_synchronize.py
Windows users: steelsquid_synchronize.exe
All files will now sync to the Raspberry Pi.
I also recommend changing the development mode.
In the synchronization program window execute: steelsquid dev-on
It should look like this:
# steelsquid dev-on
2015-12-17 21:22:52 Command executed OK |
Connect LED and buttons to Raspberry Pi
Connect all the LED cathode to the GND on the Raspberry.
Also connect the buttons to GND.
Raspberry |
Button/LED |
GND |
Button up |
GND |
Button down |
GND |
All LED cathode |
GPIO15 |
Button up |
GPIO14 |
Button down |
GPIO25 |
LED 10 (top) |
GPIO24 |
LED 9 |
GPIO23 |
LED 8 |
GPIO18 |
LED 7 |
GPIO04 |
LED 6 |
GPIO17 |
LED 5 |
GPIO27 |
LED 4 |
GPIO22 |
LED 3 |
GPIO10 |
LED 2 |
GPIO09 |
LED 1 (bottom) |
The module containing all logic
You can add all logic to kiss_expand.py directly but i recommend that you create a new file .
In the synchronization program window press N then enter the name of the module.
Use the name: led_bar
# n
Enter name of module to create: led_bar
2015-12-18 12:39:09 Creating new module led_bar.py in modules/
Restart the steelsquid service for this to take effect (type A and enter)
#
2015-12-18 12:39:10 SYNC: modules/led_bar.py
|
Now there is a file under modules/ named led_bar.py, it is a copy of kiss_expand.py.
Open the file in you favorite editor .
I will now add all that is needed in this new file, or you can just copy the entire file at once.
I think the comments in the code says it all...
- Import module
In the top of the file where the import is add: import os
- Remove unused stuff
Search for class SOCKET(object) and class PIIO(object)
You can remove both those classes and the content of them
- The enable and disable methods
I do not use this in the example but can be useful if you want to do some thing when this module is enabled or disabled. Maybe you want to create a file och enable other modules...
# Is this module started
# This is set by the system automatically.
is_started = False
def on_start():
'''
When this module is enabled what needs to be done (execute: steelsquid module XXX on)
Maybe you need create some files or enable other stuff.
'''
pass
def on_stop():
'''
When this module is disabled what needs to be done (execute: steelsquid module XXX off)
Maybe you need remove some files or disable other stuff.
'''
pass |
- The SYSTEM class
Make the SYSTEM class look like this.
class SYSTEM(object):
'''
Methods in this class will be executed by the system if module is enabled
on_start() exist it will be executed when system starts (boot)
on_stop() exist it will be executed when system stops (shutdown)
on_network(status, wired, wifi_ssid, wifi, wan) exist it will be execute on network up or down
on_vpn(status, name, ip) This will fire when a VPN connection is enabled/disabled.
on_bluetooth(status) exist it will be execute on bluetooth enabled
on_mount(type_of_mount, remote, local) This will fire when USB, Samba(windows share) or SSH is mounted.
on_umount(type_of_mount, remote, local) This will fire when USB, Samba(windows share) or SSH is unmounted.
on_event_data(key, value) exist it will execute when data is changed with steelsquid_kiss_global.set_event_data(key, value)
'''
# I do not want the ledbars to change on the first network event, or the saved value from disk will
# have no purpuse
first_network_change = True
@staticmethod
def on_start():
'''
This will execute when system starts
Do not execute long running stuff here, do it in on_loop...
'''
steelsquid_utils.shout("The LED bar is enabled")
# Read number of lit LEDs from disk, if not found on the disk use 5
led_bars_lit = int(steelsquid_utils.get_parameter("led_bars_lit", "5"))
# USING global for the logic to lit the led-bar
GLOBAL.led_bars_lit(led_bars_lit)
# Listen for click on button s
# When GPIO state change from hight>low>hight fire a method
# The button is connected to GND (when button is clicked gpio is LOW) that
# why i use resistor=PULL_UP
steelsquid_pi.gpio_click(15, SYSTEM.on_button_increase, resistor=steelsquid_pi.PULL_UP) # Listen
steelsquid_pi.gpio_click(14, SYSTEM.on_button_decrease, resistor=steelsquid_pi.PULL_UP) # Listen
@staticmethod
def on_stop():
'''
This will execute when system stops
Do not execute long running stuff here
'''
steelsquid_utils.shout("The LED bar disabled")
# Turn of all led
GLOBAL.led_bars_lit(0, save_to_disk=False)
# Stop listen for click on buttons
steelsquid_pi.gpio_event_remove(15)
steelsquid_pi.gpio_event_remove(14)
@staticmethod
def on_loop():
'''
This will execute over and over again untill it return None or -1
If it return a number larger than 0 it will sleep for that number of seconds before execute again.
If it return 0 it will not not sleep, will execute again immediately.
'''
# Is there a file in the /root directory named flash
if os.path.isfile("/root/flash"):
# Remove the file
os.remove('/root/flash')
# Lit all the LEDs
GLOBAL.led_bars_lit(10, save_to_disk=False, save_number_led_bars_lit=False)
# Afer a second show the old number of leds
steelsquid_utils.execute_delay(1, GLOBAL.led_bars_lit, (None,))
# Will sleep for half a seconds before execute again
return 0.5
@staticmethod
def on_network(status, wired, wifi_ssid, wifi, wan):
'''
Execute on network up or down.
status = True/False (up or down)
wired = Wired ip number
wifi_ssid = Cnnected to this wifi
wifi = Wifi ip number
wan = Ip on the internet
'''
# I do not want the ledbars to change on the first network event, or the saved value from disk will
# have no purpuse
if SYSTEM.first_network_change:
SYSTEM.first_network_change=False
else:
# If network is up lit all led and if network is down lit no led
if status==True:
GLOBAL.led_bars_lit(10)
else:
GLOBAL.led_bars_lit(0)
@staticmethod
def on_button_increase(gpio):
'''
Fire when the up button is clicked
@param gpio: The gpio
'''
steelsquid_utils.shout_time("Button increase clicked")
# USING global for the logic to lit the led-bar
GLOBAL.led_bars_increase()
@staticmethod
def on_button_decrease(gpio):
'''
Fire when the down button is clicked
@param gpio: The gpio
'''
steelsquid_utils.shout_time("Button decrease clicked")
# USING global for the logic to lit the led-bar
GLOBAL.led_bars_decrease()
|
- The LOOP class
The loop class shall look like this.
class LOOP(object):
'''
Every static method with no inparameters will execute over and over again untill it return None or -1
If it return a number larger than 0 it will sleep for that number of seconds before execute again.
If it return 0 it will not not sleep, will execute again immediately.
Every method will execute in its own thread
'''
@staticmethod
def on_loop():
'''
This will execute over and over again untill it return None or -1
If it return a number larger than 0 it will sleep for that number of seconds before execute again.
If it return 0 it will not not sleep, will execute again immediately.
'''
# Is there a file in the /root directory named flash
if os.path.isfile("/root/flash"):
# Remove the file
os.remove('/root/flash')
# Lit all the LEDs
GLOBAL.led_bars_lit(10, save_to_disk=False, save_number_led_bars_lit=False)
# Afer a second show the old number of leds
steelsquid_utils.execute_delay(1, GLOBAL.led_bars_lit, (None,))
# Will sleep for half a seconds before execute again
return 0.5
|
- The WEB class
Make the WEB class look like this.
class WEB(object):
'''
Methods in this class will be executed by the webserver if activate() return True and the webserver
is enabled
If is a GET it will return files and if it is a POST it executed commands.
It is meant to be used as follows.
1. Make a call from the browser (GET) and a html page is returned back.
2. This html page then make AJAX (POST) call to the server to retrieve or update data.
3. The data sent to and from the server can just be a simple list of strings.
For more examples how it work:
- steelsquid_http_server.py
- steelsquid_kiss_http_server.py
- web/index.html
'''
@staticmethod
def ledbar_get(session_id, parameters):
'''
This is a request from the web page led_bar.html
Get status of lit LED (how many is lit)
@param session_id: A session id
@param parameters: Paramaters from the web page request
(a list of paramaters)
'''
# Return number of lit to the web page
return [GLOBAL.number_led_bars_lit]
@staticmethod
def ledbar_set(session_id, parameters):
'''
This is a request from the web page led_bar.html
Set status of lit LED (how many should be lit)
@param session_id: A session id
@param parameters: Paramaters from the web page request
(a list of paramaters)
'''
# Get number fron the webpage request
number = int(parameters[0])
# Check if walue is OK
if number < 1 or number > 10:
# This text will show in a popup on the web page
raise Exception("Value must be between 1 and 10!")
# Set the number of lit LEDs
GLOBAL.led_bars_lit(number)
# Return number of lit to the web page
return [GLOBAL.number_led_bars_lit]
@staticmethod
def ledbar_increase(session_id, parameters):
'''
This is a request from the web page led_bar.html
Increase number of lit LED
@param session_id: A session id
@param parameters: Paramaters from the web page request
(a list of paramaters)
'''
# Increase the number of lit LEDs
GLOBAL.led_bars_increase()
# Return number of lit to the web page
return [GLOBAL.number_led_bars_lit]
@staticmethod
def ledbar_decrease(session_id, parameters):
'''
This is a request from the web page led_bar.html
Decrease number of lit LED
@param session_id: A session id
@param parameters: Paramaters from the web page request
(a list of paramaters)
'''
# Decrease the number of lit LEDs
GLOBAL.led_bars_decrease()
# Return number of lit to the web page
return [GLOBAL.number_led_bars_lit] |
- The EVENTS class
I do not use any events in this example, so you can leave it blank or remove it...
class EVENTS(object):
'''
Create staticmethods in this class to listen for asynchronous events.
Example: If you have a method like this:
@staticmethod
def this_is_a_event(a_parameter, another_parameter):
print a_parameter+":"+another_parameter
Then if a thread somewhere in the system execute this:
steelsquid_kiss_global.broadcast_event("this_is_a_event", ("para1", "para2",))
The method def this_is_a_event will execute asynchronous
'''
|
- The GLOBAL class
Make the GLOBAL class look like this.
class GLOBAL(object):
'''
Put global staticmethods in this class, methods you use from different part of the system.
Maybe the same methods is used from the WEB, SOCKET or other part, then put that method her.
It is not necessary to put it her, you can also put it direcly in the module (but i think it is
kind of nice to have it inside this class)
'''
# Map number of led to gpio
GPIO_MAPING = [9, 10, 22, 27, 17, 4, 18, 23, 24, 25]
# How many LEDs is lit now
number_led_bars_lit=0
@staticmethod
def led_bars_lit(nr_led_bars_lit=None, save_to_disk=True, save_number_led_bars_lit=True):
'''
Lit number of LED that should be lit.
'''
steelsquid_utils.debug("led_bars_lit")
# Should i change the GLOBAL.number_led_bars_lit
if nr_led_bars_lit!=None and save_number_led_bars_lit:
GLOBAL.number_led_bars_lit = int(nr_led_bars_lit)
# What should i use when iterting the leds
if nr_led_bars_lit !=None and not save_number_led_bars_lit:
iterate_on_this = nr_led_bars_lit
else:
iterate_on_this = GLOBAL.number_led_bars_lit
# Set GPIO hight or low depending on how many led i want to lit
for i in range(0, 10):
if i < iterate_on_this:
steelsquid_pi.gpio_set(GLOBAL.GPIO_MAPING[i], True)
else:
steelsquid_pi.gpio_set(GLOBAL.GPIO_MAPING[i], False)
# Save value to disk
if save_to_disk:
steelsquid_utils.set_parameter("led_bars_lit", GLOBAL.number_led_bars_lit)
steelsquid_utils.shout_time("Number of LED glowing: " + str(GLOBAL.number_led_bars_lit))
@staticmethod
def led_bars_increase():
'''
Will light one more LED.
'''
steelsquid_utils.debug("led_bar_increase")
if GLOBAL.number_led_bars_lit < 10:
GLOBAL.number_led_bars_lit = GLOBAL.number_led_bars_lit + 1
GLOBAL.led_bars_lit()
@staticmethod
def led_bars_decrease():
'''
Will light one less LED.
'''
steelsquid_utils.debug("led_bar_decrease")
if GLOBAL.number_led_bars_lit > 1:
GLOBAL.number_led_bars_lit = GLOBAL.number_led_bars_lit - 1
GLOBAL.led_bars_lit()
|
Activate the module
For the module to start on boot you need to activate it.
Do that by E in the synchronization program and select the module (led_bar) # e STATUS MODULE NAME ----------------------------------------------- 1 [Enabled] led_bar 2 [Disabled] steelsquid_kiss_alarm 3 [Disabled] steelsquid_kiss_expand 4 [Disabled] steelsquid_kiss_piio 5 [Disabled] steelsquid_kiss_rover Enter number of the module to enable (1, 2, 3...): 1 2016-01-02 14:36:14 Request enable of module: kiss_piio
# |
The steelsquid service will restart....
If you press L you will see that the module enabled:
# l
STATUS MODULE NAME
-----------------------------------------------
[Enabled] led_bar
[Disabled] steelsquid_kiss_alarm
[Disabled] steelsquid_kiss_expand
[Disabled] steelsquid_kiss_piio
[Disabled] steelsquid_kiss_rover
|
The HTML interface
You can use the file web/expand.html directly or create a new . In this example we create a new.
In the synchronization program window press W then enter the name of the html file.
You can use any name you want, but in this example i use the same as the module.
Use the name: led_bar
# w
Enter name of html file to create: led_bar
2015-12-18 12:40:05 Creating new html file led_bar.html in web/
#
2015-12-18 12:40:06 SYNC: web/led_bar.html
|
Now there is a file under web/ named led_bar.py, it is a copy of template.html.
Open the file in you favorite editor and add make it look like this (just copy and past all):
I think it is pretty easy to understand if you know HTML...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>LCD BAR test</title>
<meta http-equiv="Content-Language" content="en" />
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta name="LED bar" content="Example how to use Steelsquid KISS OS" />
<meta name="keywords" content="led, example" />
<meta name="author" content="Andreas Nilsson (Steelsquid)" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link rel="icon" href="favicon.ico" type="image/x-icon"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" type="text/css" href="steelsquid.css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="steelsquid.js"></script>
<script type="text/javascript">
//<![CDATA[
/**
* This will execute when the page is loaded
*/
function onPageLoad(){
//Get the number of lit LED on page load
submitNoPW('ledbar_get');
}
/**
* This will execute every 1 second
*/
function onEvery01s(){
//Get the number of lit LED every 1 second
submitNoPW('ledbar_get');
}
/**
* This is the answer from the server for the request ledbar_get (submitNoPW('ledbar_get'))
* The answer is the list returned from the function with the same name in led_bar.py
*/
function on_ledbar_get(paramaters){
number = paramaters[0];
setContent("number_of_led", number);
}
/**
* This is the answer from the server for the request ledbar_set
* The answer is the list returned from the function with the same name in led_bar.py
*/
function on_ledbar_set(paramaters){
//The answer is the same as request ledbar_get
on_ledbar_get(paramaters);
}
/**
* This is the answer from the server for the request ledbar_increase
* The answer is the list returned from the function with the same name in
* steelsquid_kiss_http_expand.py
*/
function on_ledbar_increase(paramaters){
//The answer is the same as request ledbar_get
on_ledbar_get(paramaters);
}
/**
* This is the answer from the server for the request ledbar_decrease
* The answer is the list returned from the function with the same name in
* steelsquid_kiss_http_expand.py
*/
function on_ledbar_decrease(paramaters){
//The answer is the same as request ledbar_get
on_ledbar_get(paramaters);
}
//]]>
</script>
</head>
<body>
<h1>The LED Bar web interface</h1>
<div><br/></div>
<div>This is the number of lit LEDs, updated every 1 seconds.</div>
<table class="keyvalue">
<tbody>
<tr>
<td>
Number of LED lit:
</td>
<td id="number_of_led">
</td>
</tr>
</tbody>
</table>
<div><br/></div>
<table class="input">
<tbody>
<tr>
<td>
Set number of lit LED
</td>
</tr>
<tr>
<td>
<input type="text" id="change_lit_led"></input>
</td>
</tr>
<tr>
<td>
<!--
This will submit the request ledbar_set with value from the input form
change_lit_led as paramater
-->
<button onclick="javascript:submitSyncFromInput('ledbar_set', 'change_lit_led')">
Set
</button>
</td>
</tr>
</tbody>
</table>
<div><br/><br/></div>
<table class="grid">
<tbody>
<tr>
<td colspan = "2">
Increase/decrease number of lit LED
</td>
</tr>
<tr>
<td>
<!-- This will submit the request ledbar_decrease -->
<button onclick="javascript:submitSync('ledbar_decrease')">Decrease</button>
</td>
<td>
<!-- This will submit the request ledbar_increase -->
<button onclick="javascript:submitSync('ledbar_increase')">Increase</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>
|
Test it
The synchronization program should have upload the 2 new files for you.
To be absolutely sure that all your changes had bean implemented, you can write S and pressing Enter in the synchronization program.
# s 2015-12-27 15:05:08 Request service restart
#
|
The steelsquid daemon is then restarted
Enter http://<ip to your raspberry>/led_bar in your browser
You should see this page:
- Test to push the buttons and set the number of LED to be lit.
- Also test to push the buttons connected to the GPIO
When you do that the "Number of LED lit" value in the web should change also.
- If you unplug the network cable or unplug the WIFI usb card all the LED should turn off and when you put it back in all should lit.
- Press the button so you have about half the LED lit.
In the synchronization program window type: echo "" > /root/flash
And all the LED should lit for 1 second and then go back to the number before.
That's it :-)
|
|