Close
0%
0%

Easy RasPi configuration

Allow customers to easily configure your RasPi product.

Public Chat
Similar projects worth following
How does your customer configure a RasPi product?

Specifically, if you sell a product with an embedded RasPi, how does the user:
- Enter their WiFi password?
- Connect to their filesharing workgroup?
- Set a fixed IP address?
- Disable Wifi and use ethernet?
- Choose a name for their system?

End-users might not have a spare display and keyboard available. Navigating linux is complicated, and configuration requires superuser mode.

This project provides a way for end-users to easily configure a RasPi system.

The "AppDaemon" runs your application while monitoring a GPIO button. When pressed, the system will stop your application and broadcast an access point with the name of the system. When the user connects to that AP using any browser, they are presented with web pages that allow easy access to the settings.

When changes are saved, the system will reboot and continue running your application.

This project is open source and free to use.

How it works

The "AppDaemon" runs your application (your product software) at system boot. If your application crashes or hangs, the daemon will automatically reboot the system.

The AppDaemon also monitors a GPIO button. When pressed, the system will stop your application and switch to Access Point mode. It will broadcast an access point with the name of the system, in "captive portal" mode: any web access the user makes will be redirected to the local web server (the configuration pages). It's the mode used by public hotspots and airport  WiFi to show a login page before allowing internet access.

When the user connects to the access point and opens a browser, they are presented with configuration panels to set system parameters such as the WiFi name and password.

When the user saves the configuration, the system will reboot and continue your product application.

Monitoring the product application

The AppDaemon is given an application to run, and will monitor that application for correct execution. If the application crashes, hangs, or exits the AppDaemon will reboot the system and rerun the application.

The intent is for a high-reliability system where one process is doing something which might hang, crash, or otherwise become a problem. When a problem with the application is detected, this daemon will reboot and presumably clear the error.

(This was originally for cell modem applications, because a cell modem can crash or hang for myriad reasons, and sometimes detecting that a problem exists is impossible.)

Integrating with your product application

The system is intended to be integrated into your application codebase.

After installing the project (using "git clone") and getting the sample application to run, simply replace the pathname of the sample application with the pathname of your application.

Comment out the configuration pages that don't apply to your system, and add a page that configures your application if you need one. Add some informative text to the "info" page that describes your application - there are instructions for doing this in the project.

Add your product branding to the configuration pages as needed: background color, fonts and styles, trademarks, and corporate logos.

This product is open source and free to use without attribution. Contact me through this site if you need a more definitive legal document. (See "private messages" at top of page.)

Built-in web page server

The AppDaemon has a built-in web page server for use by your application. Place "index.html" and whatever support pages you need (index.css, favicon.ico) in a separate directory and add the "WebDir=<that-directory>" to the AppDaemon line in rc.local.

When "WebDir" is supplied as an argument, a web server will be started in that directory while your application is running.

This is a *simple* web page server without sophisted processing or security. If you need more functionality, install and use Apache.

Bugs and errors

Please let me know about bugs and other issues so I can update the project.

  • Found a bug - looking for suggestions

    Peter Walsh11/30/2020 at 17:39 0 comments

    I found a bug in the way AppDaemon responds to program exit.

    Normally the AppDaemon will reboot the system if the user App exits. This is by design, to keep the application running because most problems can be fixed with a reboot.

    The reboot is cancelled if a user is logged in to the system, also by design. The idea is that that user is probably debugging the system or otherwise engaged, and you don't want to boot users from the system anyway.

    This works well for the command-line version of Raspbian: by default no users are logged in, and logged-in users are shown on the "users" command. The default GUI version automatically logs in the pi user, so the "users" command shows users logged in even if no one is on the system. This means that the AppDaemon won't reboot the system if the user App fails.

    I could change the system to not reboot if an SSH user is logged in. That would boot GUI users of the user App fails, but that's probably OK because if you're debugging the system through an attached display and KB you should disable the AppDaemon anyway.

    If I don't change anything, the default GUI system will never reboot the system when the app fails. OTOH that might be OK because the user really shouldn't be automatically logging in the user.

    Any suggestions?

  • New version adds web server

    Peter Walsh11/24/2020 at 16:40 0 comments

    Made some changes for clarity, and added a web server feature available to user applications.

    AppDarmon starts at system boot via command in /etc/rc.local. If you add the argument "WebDir=<some-directory>", the system will start a web server in that directory along with your application. Place an index.html in that directory and whatever support files you might need (index.css, index.js, favicon.ico), and these will be served on port 80 with your application.

    This is a *simple* web server, based on the javascript html library, so it doesn't do sophisticated processing or security controls or .htaccess.

    If you need full website functionality, install and use Apache.

    But if you just need a simple page or two for your application, you can use the built-in one supplied with the AppDaemon.

    Here's how you might modify rc.local to make use of this feature:

    ConfigGPIO=4;       # Config switch WPi07, Connector pin  7, GPIO (command) BCM 04                                                                                                
    LEDGPIO=19;         # Config LED    WPi24, Connector pin 35, GPIO (command) BCM 19                                                                                                
    
    Verbose="-v"        # AppDaemon gets very talky                                                                                                                                   
    #Verbose=           # AppDaemon shuts up                                                                                                                                          
    
    nohup /root/AppDaemon/bin/AppDaemon $Verbose --config-gpio=$ConfigGPIO --led-gpio=$LEDGPIO  \
                                                 --web-dir /home/pi/GPIOServer/public_html      \
                                                 --user=pi /home/pi/GPIOServer/bin/GPIOServer &
    

    And with that example, here are the files the application would need:

    /home/pi/GPIOServer/public_html: l
    favicon.ico  GPIOServer.css  GPIOServer.js  images  index.html  success.txt
    

    For reference, here's the full command line documentation for the AppDaemon:

    ##  USAGE                                                                                                                                                                         
    ##                                                                                                                                                                                
    ##      AppDaemon [-v] --SSID=<name> --config-gpio=<gpio#> --led-gpio=<gpio#> --web-dir=<dir> --user=<user> App1 [App2 ... ]                                                      
    ##                                                                                                                                                                                
    ##      where:                                                                                                                                                                    
    ##                                                                                                                                                                                
    ##          --SSID=name             Name to show when in access point mode                                                                                                        
    ##                                                                                                                                                                                
    ##          --config-gpio=#         GPIO of button to enter config mode                                                                                                           
    ##                                                                                                                                                                                
    ##          --led-gpio=#            GPIO of LED (to blink when in AP mode)                                                                                                        
    ##                                                                                                                                                                                
    ##          --user=<user>           User to run applications as (ie - "pi" for raspberry pi default user)                                                                         
    ##                                                                                                                                                                                
    ##          App[n]                  Applications to run and monitor                                                                                                               
    ##                                                                                                                                                                                
    ##          --web-dir=<dir>         Spark a web server in this directory, in addition to any apps                                                                                 
    ##                                                                                                                                                                                
    ##          -verbose                Print out things as they happen                                                                                                               
    ##          -v                                                                                                                                                                    
    ##                                                                                                                                                                                
    ##          If ap-name is not given, will use the text in /etc/hostname. If this file is blank or                                                                                 
    ##            missing, will use the literal "RasPi"                                                                                                                               
    ##                                                                                                                                                                                
    ##          If led-gpio is not given, will not attempt to blink anything when entering config mode.                                                                               
    ##                                                                                                                                                                                
    ##          If config-gpio is not given, will not enter config/ap mode.                                                                                                           
    ##                                                                                                                                                                                
    ##          If user is not given, will use "pi"                                                                                                                                   
    

  • Front page of Hackaday

    Peter Walsh11/19/2020 at 01:11 0 comments

    Looks like my project made the front page of Hackaday. Woot!

    And I got one (yes, one!) like for my completely awful video. Life is good.

    I have some changes and upgrades to make but I'll be holding them back for the time being, on the off chance that I break something while people are grabbing the project.


    One change is to make the web page server a user feature of the AppDaemon, so if your project has a web page, the AppDaemon can spark a web server for you automatically without having to install Apache.

  • Initial release

    Peter Walsh11/15/2020 at 18:17 0 comments

    System is released and available. New screencaps are up, and today I'll make a video showing how it works.

    Enjoy!

  • Tomorrow looks good for initial release

    Peter Walsh11/03/2020 at 19:47 0 comments

    Most of the functionality is implemented and working, only need to add some things from the todo list and do a little testing. Also, sprucing up the web page a little.

    Little things, like doing a syntax check on some of the fields (the static fields in particular), so the user can't typo an invalid entry.

    Tomorrow looks good for an initial release.

    I still need to implement the FileSharing page, but the underlying code to make actual changes is done, so it should only be a matter of formatting the web page.

    I now have a system for easily parsing any of the linux data formats - either from config files (dhcpcd.conf) or commands (iwlist). For example, I have a function "GetDHCPInfo()" that returns the struct listed below.

    In addition to being easy to work with this data in perl, the parser system also makes note of where it found each data item, so that updates can happen inline in the config file. Setting "DNS2->{NewValue} = "4.4.4.4" and calling $Parser->Update() will change the corresponding field within the original file. Boo-yah!

    'DHCPInfo' => {
           'wlan0' => {
                        'DNS1' => '1.1.1.1',
                        'Enabled' => 1,
                        'IPAddr' => '192.168.1.31/24',
                        'Router' => '192.168.1.1',
                        'DNS2' => '1.0.0.1',
                        'DHCP' => 0
                      },
           'eth0' => {
                       'DHCP' => 1,
                       'Router' => '',
                       'IPAddr' => '',
                       'DNS2' => '',
                       'Enabled' => 1,
                       'DNS1' => ''
                     },
           'wlan1' => {
                        'Enabled' => 0,
                        'DNS1' => '',
                        'Router' => '',
                        'DNS2' => '',
                        'IPAddr' => '',
                        'DHCP' => 1
                      }
         },
    

    There's some devil in the details. For example, if a static block does not already exist in the file then the caller has to add it manually, but there's helper functions to do this. Here's how easy it is to add a new static block to the end of dhcpcd.conf:


    my $IFConfig = [
        "",
        "interface $IFName",
        "    static ip_address=$IPAddr",
        "    static routers=$Router",
        "    static domain_name_servers=$DNSS1 $DNS2",
        ""];
    
        $ConfigFile->AddLines($IFConfig);
    

    If there's any interest I might upload the parser to CPAN. It's pretty useful, and can be used to parse just about any simple data layout.

  • Release delayed by 1 week

    Peter Walsh10/31/2020 at 13:52 0 comments

    Yesterday I spent 6 hours trying to get two icons to line up the way I wanted!

    ...on the plus side, it looks like I'm learning little more about HTML. There's some better screenshots in the project that will give you a sense of what the project will look like.

    (**Update: that was yesterday. Today it took me only 3 hours (minus 10 min) to make the code that actually *sets* all the configuration parameters - all of it. I hate HTML.)

    I also found bugs that need to be addressed before release. Most importantly, one of my clients uses an external Wifi dongle for his project (the RasPi is mounted inside a metal box, so he has to have an external antenna), so the system needs to be able to deal with two (or more) WiFi devices.

    The "device" configuration page should work OK, but the WiFi SSID/password selection page assumes the wlan0 device.

    I slipped the release date by a week.

    Here's what the Wifi settings page looks like:

  • Network Device config

    Peter Walsh10/29/2020 at 23:15 0 comments

    I've been busy banging on the project pretty reliably for the past two weeks. It's taking me longer to complete than I had originally estimated - there's no problem, there's just more of it than I originally thought.

    I still expect to be done by Nov 1st. Well... at least the *week* of November 1st.

    One application for this project is a friend's "remote work" relay hat for Raspberry Pi systems, so remote workers can power cycle hardware in the lab remotely. The project allows a remote user to view a web page on the RasPi system with buttons to toggle the relays, or use small executables (little JSON web socket programs in python) that can be mapped to a keyboard key or similar.

    Something like: ToggleGPIO 13 mycompany.com

    Where: "ToggleGPIO" is a small program that can be run anywhere on the internet and access the RasPi server running the relays.

    Remote relays are available on eBay that can be controlled by Wifi, bluetooth, IR and so on, but my friend's client doesn't allow Chinese-made devices on their network.

    So one benefit of using the AppDaemon system is it's open source that can be examined by anyone. No backdoors, no stealing data, nothing.

    And one of [the client's] requirements was to disable unused network interface devices for security, so I had to add a page that lets the end user:

    • Enable or disable a network interface
    • Use DHCP or static IPV4
    • Set the various IPV4 fields

    This in addition to the WiFi SSID and password config, which was already complete.

    This was a little more config than originally planned, but it's done now. It's all working, except the web page needs some sprucing up for better looks. I also have to add the back-end sections that set the new config data, but since it's not HTML or javascript I think that'll be easy.

View all 7 project logs

  • 1
    Installing AppDaemon

    This is an application-level program, not a system command or system feature. It is an add-on to your product software, and as such there is no global "apt-get install". You will need a copy of the source to modify for your needs.

    Step 1: Copy the project to the /root directory.

    > sudo su
    > cd /root
    > git clone https://github.com/ToolChainGang/AppDaemon.git
    

    Step 2: Upgrade your system

    The subdirectory "install" contains scripts to upgrade your system and install needed packages.

    For proper installation, each script should be run multiple times, fixing errors as needed, until the output contains nothing but a list of "already have most recent version" messages.

    (as root)
    
    > cd /root/AppDaemon/install
    > ./05-UpgradeInstall.sh
    
    Go get lunch, then rerun the script
    
    > ./05-UpgradeInstall.sh
    
    Verify that the output contains nothing but
    a list of "newest version" messages.
    
    > ./06-UpgradePerl.sh
    
    Go get dinner, then rerun the script
    
    > ./06-UpgradePerl.sh
    
    Verify that the output contains nothing but
    a list of "newest version" messages.

    Step 3: Test your GPIO hardware

    The install directory contains a testing app that uses the same GPIO logic as the AppDaemon.

    Execute that app with your GPIO settings and verify that the config button hardware works, your LED blinks (if you use a config LED), and so on.

    For example:

    > GPIOTest --config-gpio=4 --led-gpio=19
    

    Step 4: Install the test application

    The install subdirectory contains a sample application (SampleApp) for testing.

    Copy that application to the /home/pi directory, change the owner to pi:pi, then add a line to your /etc/rc.local file that invokes the AppDaemon with that file.

    For example, put this in your /etc/rc.local file:

    ########################################################################################################################
    #
    # Start the AppDaemon
    #
    set +e
    
    ConfigGPIO=4;       # Config switch WPi07, Connector pin  7, GPIO (command) BCM 04
    LEDGPIO=19;         # Config LED    WPi24, Connector pin 35, GPIO (command) BCM 19
    
    nohup /root/AppDaemon/bin/AppDaemon   --config-gpio=$ConfigGPIO --led-gpio=$LEDGPIO --user=pi /home/pi/SampleApp &
    #nohup /root/AppDaemon/bin/AppDaemon -v --config-gpio=$ConfigGPIO --led-gpio=$LEDGPIO --user=pi /home/pi/SampleApp &
    
    set -e
    

    A sample rc.local file that does this is included with the project, so for a quick test you can do the following:

    (as root)
    > cd /root/AppDaemon/install
    > cp SampleApp /home/pi/
    > chown pi:pi /home/pi/SampleApp
    > cp /etc/rc.local /etc/rc.local.bak
    > cp rc.local.SAMPLE /etc/rc.local
    > reboot
    

    ```

    Step 4: Connect the AppDaemon to your application

    Once everything is running the /root/AppDaemon/install directory is no longer needed - you can delete it.

    Change the link in rc.local to run your application instead of the SampleApp, and you're good to go.

View all instructions

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates