B4J Tutorial [ABMaterial]Raspberry Pi Switch LED

Discussion in 'B4J Tutorials' started by rwblinn, Nov 30, 2016.

  1. rwblinn

    rwblinn Well-Known Member Licensed User

    Sharing my experience in building my first ABMaterial WebApp running on a Raspberry Pi (RPi).
    Note: any hints on improvements appreciated ;)

    Objective

    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 here.

    Project Folder
    Create folder <path>\LEDSwitch.

    Project Files
    Copy folder \abmaterial\template to <path>\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():
    Code:
    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)
    Code:
    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!
    Code:
    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!).
    Code:
    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:
    Code:
    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}http://www.rwblinn.de{AT}rwblinn.de{/AL}{BR}{BR}${Main.Version}"$,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}http://alwaysbusycorner.com/abmaterial{AT}Alain Bailleul{/AL}{BR}{BR}B4J by {AL}http://www.bx4.com{AT}Anywhere 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 (read here).
    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.
    Code:
    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:
    Code:
    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.
    Code:
    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 log:
    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, 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 here.

    Screenshot Browser
    upload_2016-11-30_17-58-22.png

    Enjoy!
     
    Last edited: May 8, 2017
  2. alwaysbusy

    alwaysbusy Expert Licensed User

    Very nice tutorial! Thank you for sharing. Just mentioning this requires ABMaterial 2.00+ (I see it because of the little led in the right top corner ;) )
     
    jinyistudio, joulongleu and rwblinn like this.
  3. Harris

    Harris Well-Known Member Licensed User


    I think he did...
     
    joulongleu likes this.
  4. Gary Miyakawa

    Gary Miyakawa Active Member Licensed User

    This is my first attempt with ABMaterial so I'm not certain I've got it completely installed correctly.

    I'm pretty sure it's something I'm doing wrong but after running the application (downloading the .zip) and installing... All I'm getting is 3 rings spinning in the middle of the screen.

    Is that something missing from my ABMaterial Install or ???

    Also, there appears to have been a change in the AppPage.InitializeWithTheme command. It now requires another field (SessionMaxInactiveIntervalSeconds) so I added it as a 10.

    Any suggestions would be greatly appreciated!

    Cheers,

    Gary Miyakawa
     
    joulongleu likes this.
  5. rwblinn

    rwblinn Well-Known Member Licensed User

    Hi,

    thanks for bringing up - verified installation against ABMaterial 3.03. Beside the changes required for
    • SessionMaxInactiveIntervalSeconds - set to 10
    • Raspberry Pi 3 installing the latest version of wiringPi (2.44) and Pi4J 1.2 snapshot - to be able to use the BCM2835 Hardware
    the app is running fine (note: changed port to 51042 as using as default in my browser).
    • Is the ABMaterial 3.03 www folder copied to the project folder and also on the Raspberry Pi?
    • What output is given when starting the jar?
    Example Output when starting the jar and switching the LED few times after connecting http://192.168.0.8:51042/LEDSwitch
    Code:
    pi@raspberrypi:~/b4j/ledswitch $ sudo java -jar LEDSwitch.jar
    Building core.min.css...
    2017-05-06 10:40:27.809:INFO::main: Logging initialized @1763ms
    2017-05-06 10:40:28.160:INFO:oejs.Server:main: jetty-9.3.z-SNAPSHOT
    2017-05-06 10:40:28.457:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1205a84{/,file:///home/pi/b4j/ledswitch/www/,AVAILABLE}
    2017-05-06 10:40:28.464:INFO:oejs.AbstractNCSARequestLog:main: Opened /home/pi/b4j/ledswitch/logs/b4j-2017_05_06.request.log
    2017-05-06 10:40:28.514:INFO:oejs.ServerConnector:main: Started ServerConnector@11f0959{HTTP/1.1,[http/1.1]}{0.0.0.0:51042}
    2017-05-06 10:40:28.516:INFO:oejs.Server:main: Started @2475ms
    WebSocket Connected
    Waiting for value (8 ms)
    LED Switch clicked to true
    Waiting for value (10 ms)
    Waiting for value (8 ms)
    LED Switch clicked to false
    Waiting for value (6 ms)
    Waiting for value (7 ms)
    upload_2017-5-6_10-53-34.png
     
    joulongleu and alwaysbusy like this.
  6. Gary Miyakawa

    Gary Miyakawa Active Member Licensed User

    I see the www directory on both the Project and in the RPI. They appear to be the same.

    I appear to get all the messages you get up to the WebSocket Connected (which, never appears)...

    Here is what I get:
    2017-05-06 22:00:18.897:INFO::main: Logging initialized @1784ms
    2017-05-06 22:00:19.281:INFO:eek:ejs.Server:main: jetty-9.3.z-SNAPSHOT
    2017-05-06 22:00:19.617:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1907bac{/,file:///home/pi/tempjars/www/,AVAILABLE}
    2017-05-06 22:00:19.626:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened /home/pi/tempjars/logs/b4j-2017_05_07.request.log
    2017-05-06 22:00:19.709:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@199d22e{HTTP/1.1,[http/1.1]}{0.0.0.0:51044}
    2017-05-06 22:00:19.711:INFO:eek:ejs.Server:main: Started @2612ms

    I'm missing something, obviously....

    Thanks for the help!

    Gary Miyakawa
     
  7. rwblinn

    rwblinn Well-Known Member Licensed User

    Seems a communication issue.

    Can you run the ABMaterial Demo from the Raspberry Pi?
     
  8. Cableguy

    Cableguy Expert Licensed User

    in the RPI side, as it is acting like the server, both TCP and UDP must be allowed for the sockets to function...
    At least, on my vps is what I had to do! (Firewall)
     
  9. Gary Miyakawa

    Gary Miyakawa Active Member Licensed User

    When I go to load the abmaterial demo, I get "missing parameter" errors around the page.cell(2,1).setfixedheight(800). I've added "True" there to meet parameter requirements.

    As clearly stated in the documentation, I had not moved the www (js, css, etc) files to the output area on the RPi. Once I moved those, all works as designed.

    Thanks for the help everyone !

    Gary Miyakawa
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice