### Raspberry Pi Switch LED

Sharing my experience in building my first ABMaterial WebApp running on a Raspberry Pi (RPi).
Objective
ABMaterial ( http://alwaysbusycorner.com/abmaterial ) Learning Project:
Web Application, running on a Raspberry Pi (RPi), to enable via browser, switching of an LED connected to a Raspberry Pi GPIO.
Step-by-Step Build
ABMaterial 2.00+ Library Files
Ensure the latest abmaterial.jar & xml plus other are copied from the ABM Archive Library folder to the B4J additional library folder.
See https://www.b4x.com/android/forum/threads/abmaterial-framework-for-webapps.60072/#content
Project Folder
Create folder \LEDSwitch.
Project Files
Copy folder \abmaterial\template to \LEDSwitch
Rename template.b4j and meta to LEDSwitch.b4j and LEDSwitch.b4j.meta.
Open B4J Project
Open the B4J IDE with Project LEDSwitch.b4j.
Set Project Package name
In the B4J IDE, select Project > Build Configuration and set the Package Name: com.rpi.ledswitch.
Set Title and Description
In the Class ABMApplication, set the Title and Description, which are displayed in the Browser Tab.
Modify Sub BuildPage():
`Public Sub BuildPage()
AppPage.PageTitle = "RPi LED Switch"
AppPage.PageDescription = "B4J HowTo Raspberry Pi LED switch using ABMaterial"
Set the name of the application - ensure set the right case!
In the Class ABMApplication set name and the initial page (which is created later stage)
`Sub Class_Globals
Private AppName As String = "LEDSwitch"
Private InitialPage As String = "LEDSwitchPage"
In the Class ABMPageTemplate set the AppName variable to LEDSwitch - with the same case as in ABMApplication!
`Sub Class_Globals Public AppName As String = "LEDSwitch"
Create a New Page
Create a new Server WebSocket class named LEDSwitchPage.
Copy & paste all code from the class ABMTemplatePage into the new class LEDSwitchPage.
See LEDSwitchPage.bas.
Remove the ABMTemplatePage from the project, as not required anymore.
Set the Page Name
In the Class LEDSwitchPage set the Name of the page (same as the class name (case sensitive!).
`Sub Class_Globals
Public Name As String = "LEDSwitchPage"
Add the New Page to the App
In the class Main create an instance of your new page, initialize it and add it to the app.
The Sub AppStart in Main looks like:
`Sub AppStart (Args() As String)
ABMShared.BuildTheme("mytheme")
Dim myApp As ABMApplication
myApp.Initialize
Dim LEDSwitchP As LEDSwitchPage
LEDSwitchP.Initialize
myApp.AddPage(LEDSwitchP.Page)
myApp.StartServer(srvr, "srvr", 51044)
StartMessageLoop
End Sub`
Compile and Run First Time
As this is first time, ABMaterial creates the required folders in the www folder, like
path\Objects\www\LEDSwitch\LEDSwitchPage
The B4J log example:
Collecting data from B4J source files... (1/2)
Analysing data from B4J source files... (2/2)
2016-10-17 14:23:31.665:INFO::main: Logging initialized @487ms
2016-10-17 14:23:31.775:INFO:eek:ejs.Server:main: jetty-9.3.z-SNAPSHOT
2016-10-17 14:23:31.850:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@2a079c{/,file:///C:/Daten/b4/b4j/b4jhowto/B4JHowToABMRPiGPIO/Objects/www/,AVAILABLE}
2016-10-17 14:23:31.853:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened C:\Daten\b4\b4j\b4jhowto\B4JHowToABMRPiGPIO\Objects\logs\b4j-2016_10_17.request.log
2016-10-17 14:23:32.006:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@1993335{HTTP/1.1,[http/1.1]}{0.0.0.0:51042}
2016-10-17 14:23:32.007:INFO:eek:ejs.Server:main: Started @830ms
Open a Browser and enter localhost:51044/LEDSwitch/.
This will load the pages located in LEDSwitch\LEDSwitchPage. The Browser URL is updated to localhost:51044/LEDSwitch/LEDSwitchPage.
Themes
In the Class ABMShared the themes used for this app are defined.
Note: If a Page specific Themes are needed, then create those in the Sub BuildTheme in the page (like for the class LEDSwitchPage).
`Sub BuildTheme(themeName As String)
MyTheme.Initialize(themeName)
MyTheme.Page.BackColor = ABM.COLOR_TEAL
MyTheme.Page.BackColorIntensity = ABM.INTENSITY_LIGHTEN5
MyTheme.AddRowTheme("headertheme")
MyTheme.Row("headertheme").BackColor = ABM.COLOR_TEAL
MyTheme.Row("headertheme").BackColorIntensity = ABM.INTENSITY_DARKEN1
MyTheme.AddContainerTheme("footertheme")
MyTheme.Container("footertheme").BackColor = ABM.COLOR_TEAL
MyTheme.Container("footertheme").BackColorIntensity = ABM.INTENSITY_LIGHTEN2
MyTheme.AddLabelTheme("whitefc")
MyTheme.Label("whitefc").ForeColor = ABM.COLOR_WHITE
MyTheme.AddLabelTheme("justify")
MyTheme.Label("justify").align = ABM.TEXTALIGN_JUSTIFY
MyTheme.AddLabelTheme("lightblue")
MyTheme.Label("lightblue").ForeColor = ABM.COLOR_LIGHTBLUE
MyTheme.Label("lightblue").ForeColorIntensity = ABM.INTENSITY_DARKEN2
MyTheme.AddLabelTheme("bluefc")
MyTheme.Label("bluefc").ForeColor = ABM.COLOR_BLUE
MyTheme.AddLabelTheme("redfc")
MyTheme.Label("redfc").ForeColor = ABM.COLOR_BLUE
MyTheme.AddButtonTheme("buttonon")
MyTheme.Button("buttonon").ForeColor = ABM.COLOR_WHITE
MyTheme.Button("buttonon").BackColor = ABM.COLOR_GREEN
MyTheme.AddButtonTheme("buttonoff")
MyTheme.Button("buttonoff").ForeColor = ABM.COLOR_WHITE
MyTheme.Button("buttonoff").BackColor = ABM.COLOR_RED
MyTheme.AddToastTheme("toasttheme")
MyTheme.Toast("toasttheme").ForeColor = ABM.COLOR_WHITE
MyTheme.Button("buttonoff").BackColor = ABM.COLOR_BLUE
MyTheme.Toast("toasttheme").Rounded = True
MyTheme.AddSwitchTheme("switchtheme")
MyTheme.Switch("switchtheme").SwitchOnColor = ABM.COLOR_GREEN
MyTheme.Switch("switchtheme").SwitchOnColorIntensity = ABM.INTENSITY_DARKEN4
MyTheme.Switch("switchtheme").SwitchOffColor = ABM.COLOR_RED
MyTheme.Switch("switchtheme").SwitchOffColorIntensity = ABM.INTENSITY_DARKEN4
MyTheme.Switch("switchtheme").LabelColor = ABM.COLOR_BLACK
MyTheme.Switch("switchtheme").LabelColor = ABM.INTENSITY_DARKEN4
MyTheme.Switch("switchtheme").LabelFontSize = "28px"
MyTheme.Switch("switchtheme").Colorize(ABM.COLOR_TEAL)
End Sub`
Create a Fixed Footer
In the class ABMShared add a BuildFooterFixed.
`Public Sub BuildFooterFixed(page As ABMPage)
page.isFixedFooter= True
page.PaddingBottom = 150
' Add a new row
page.Footer.AddRows(1, True, "").AddCellsOS(2,0,0,0,6,6,6, "")
' Build the grid
page.Footer.BuildGrid
page.Footer.UseTheme("footertheme")
' Add a label to Row 1, Cell 1
Dim lbl1 As ABMLabel
lbl1.Initialize(page, "footlbl1", $"B4J HowTo by {AL}[URL]http://www.mysite{AT}MySite{/AL}{BR}{BR}${Main.Version}[/URL]"$,ABM.SIZE_PARAGRAPH, False, "whitefc")
page.Footer.Cell(1,1).AddComponent(lbl1)
' Add a label to Row 1, Cell 1
Dim lbl2 As ABMLabel
lbl2.Initialize(page, "footlbl2", "ABMaterial by {AL}[URL]http://alwaysbusycorner.com/abmaterial{AT}Alain[/URL] Bailleul{/AL}{BR}{BR}B4J by {AL}[URL]http://www.bx4.com{AT}Anywhere[/URL] Software{/AL}",ABM.SIZE_PARAGRAPH, False, "whitefc")
page.Footer.Cell(1,2).AddComponent(lbl2)
End Sub`
Next Steps
The webapp initial framework has been created. Now its time to design & build the application as such:
• Define & build a shared code class for the GPIO Controller
• Design the Page Grid and its components
• Define & build the LED control logic
Define the Shared Code Class for the GPIO Controller
The GPIO Controller requires the jPi4J Library ( https://www.b4x.com/android/forum/threads/iot-jpi4j-raspberry-pi-gpio-controller.37493/#content ).
This class defines Init the GPIO Controller, set the GPIO Pin to digital output, switch the pin state to high (true) or low (false), get pin state.
See LEDController.bas.
Design the Page Grid (see also screenshot below)
In the Class LEDSwitchPage, define the page and its components in the Sub BuildPage().
There are 4 rows with cells and its ABM Controls:
• Row 1, 1 cell: Header (ABMLabel)
• Row 2, 3 cells: 1=Switch (ABMSwitch), 2=Switched info (ABMLabel), 3=Not Used
• Row 3, 1 cell: Empty
• Row 4, 1 cell: Divider (ABMDivider)
• Row 5, 1 cells: Info (ABMCard)
IMPORTANT = EACH CONTROL MUST HAVE AN UNIQUE ID.
See LEDSwitchPage.bas.
Define LED Control Logic
The event Sub SwitchLED3_Clicked handles switching and information updates via the Webpage triggered by the User.
`Sub SwitchLED3_Clicked(Target As String)
Dim LEDSwitch As ABMSwitch = page.Component("SwitchLED3")
Log($"LED Switch clicked to ${LEDSwitch.state}"$)
' Set the LED Pin state
LEDController.SetPinState(LEDController.Pin3, LEDSwitch.state)
...
In Sub Page_Ready(), the state of the LEDSwitch is set according the pin GPIO state:
Dim LEDSwitch As ABMSwitch = page.Component("SwitchLED3")
LEDSwitch.State = LEDController.GetPinState(LEDController.Pin3)
See LEDSwitchPage.bas.
In the Class Main, Sub AppStart the GPIOController is initialized prior executing the ABM Subs to build & start the application.
`Sub AppStart (Args() As String)
' Init the GPIO controller prior building the pages as the state of the pin is used by the abmswitch
LEDController.Init_GPIOController
' Set the Pin Number 3 = physical pin 15 = GPIO22 = GPIO_GEN3 as GpioPinDigitalOutput
' (the GPIO_GEN3 indicates Pin 3)
LEDController.Init_GPIOPinDigitalOutput(LEDController.Pin3,3,False)
' ABM
ABMShared.BuildTheme("mytheme")
Dim myApp As ABMApplication
myApp.Initialize
Dim LEDSwitchP As LEDSwitchPage
LEDSwitchP.Initialize
myApp.AddPage(LEDSwitchP.Page)
myApp.StartServer(srvr, "srvr", 51044)
StartMessageLoop
End Sub`
See LEDSwitch.b4j.
RPi B4J Bridge
During development, the B4J-Bridge running on the Raspberry Pi has been used.
The project www folder must be copied to the Raspberry Pi tempjars folder, e.g. /home/pi/b4j/tempjars/www/LEDSwitch/LEDSwitchPage.
Copy the files, after the previous described step "Compile and Run first time".
When compiling and run, wait till the server is running (this might take a few seconds depending Network & RPi performance). Watch the B4J IDE Logs:
2016-11-30 14:16:45.155:INFO::main: Logging initialized @2631ms
2016-11-30 14:16:45.741:INFO:eek:ejs.Server:main: jetty-9.3.z-SNAPSHOT
2016-11-30 14:16:46.212:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1e2dbf3{/,file:///home/pi/b4j/tempjars/www/,AVAILABLE}
2016-11-30 14:16:46.227:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened /home/pi/b4j/tempjars/logs/b4j-2016_11_30.request.log
2016-11-30 14:16:46.312:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@2a67b4{HTTP/1.1,[http/1.1]}{0.0.0.0:51044}
2016-11-30 14:16:46.317:INFO:eek:ejs.Server:main: Started @3803ms
WebSocket Connected
Waiting for value (11 ms)
LEDControlPage ready!
Waiting for value (14 ms)
RPi Application Folder
Create a folder /home/pi/b4j/ledswitch and copy the files from the project\objects folder. The RPi folder looks like:
/home/pi/b4j/ledswitch/BaseDefaults.def
/home/pi/b4j/ledswitch/BaseTranslations.lng
/home/pi/b4j/ledswitch/copymewithjar.needs
/home/pi/b4j/ledswitch/LEDSwitch.jar
/home/pi/b4j/ledswitch/www
Start the App
Start the app (as sudo!) from a terminal on the Raspberry Pi, e.g.
pi@33:~ $ cd b4j/ledswitch
pi@33:~/b4j/ledswitch $ sudo java -jar LEDSwitch.jar
2016-11-30 17:38:42.412:INFO::main: Logging initialized @2697ms
2016-11-30 17:38:43.015:INFO:eek:ejs.Server:main: jetty-9.3.z-SNAPSHOT
2016-11-30 17:38:43.490:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1e2dbf3{/,file:///home/pi/b4j/tempjars/www/,AVAILABLE}
2016-11-30 17:38:43.504:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened /home/pi/b4j/tempjars/logs/b4j-2016_11_30.request.log
2016-11-30 17:38:43.592:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@2a67b4{HTTP/1.1,[http/1.1]}{0.0.0.0:51044}
2016-11-30 17:38:43.597:INFO:eek:ejs.Server:main: Started @3892ms
Connected
Waiting for value (18 ms)
ready!
Disconnected
WebSocket Connected
Waiting for value (15 ms)
LEDControlPage ready!
Waiting for value (11 ms)
LED Switch clicked to true
Waiting for value (11 ms)
LED Switch clicked to false
WebSocket Disconnected
Download Source:
Documentation on request.
`````

Changed: 2018-06-07 09:28, Category: WebApps ABMaterial Framework, File: T6C278M2089.htm, ID: 2089