Create and delete files ctrlX CORE

Create and delete files and folders in Active configuration

sanX
New Contributor


Introduction

In this tutorial it will be shown how to create a snap with the capability to create and delete folders located in the snap active configuration. Additionally, this snap will be able to upload and delete files from the same active configuration folder. To be able to achieve this, a Flask webserver will be used with the purpose to provide a visualization interface and allow the user to easily upload files from the local computer to the ctrlX CORE active configuration folder. At the end of this tutorial, it will be explained how the snap works, with the purpose to allow users easily integrate this capability in their own snaps.

To find more information about data persistence, please check this explanation. Otherwise, there is also a similar How-to where these concepts are also explained.

Prerequisites
  • ctrlX Works
  • App build Environment configured
Snap development

To be able to build the snap, it is required to have the app build environment configured. To be able to perform this step, please check this tutorial.

Step 1: Download the required files

The required files can be found at the end of this tutorial

Step 2: Create project folder in the App build environment
  • Enter the app build environment and create a new folder

New folder creation in Visual Studio CodeNew folder creation in Visual Studio Code

  • Extract the zip file and drag the unzipped files folders in the new created folder.

Copy folder to project folderCopy folder to project folder

Step 3: Access the project folder
  1. Press over "File"
  2. Select "Open folder"
  3. Choose the project folder
  4. Press "Ok" and the project folder will be opened

Folder accessFolder access

Step 4: Create snap
  • Press "Terminal" and open a "New terminal"

Terminal accessTerminal access

  • Make files executable

To be able to successfully build the snap, it is required to make the bash file executable because otherwise the following message will appear:

Failure message in the case the run.sh file has not been made executableFailure message in the case the run.sh file has not been made executable

  • In the terminal, with the "cd" command, access the configs folder where the run.sh file is located:
cd configs
  • Next, use the "chmod +x" command to make the file executable:
chmod +x run.sh
  • Return to the main folder using the command "cd ..":
cd ..

Make run.sh file executableMake run.sh file executable

  • Build the snap executing the "snapcraft --destructive.mode" command:
sudo snapcraft --destructive-mode --target-arch=arm64 --enable-experimental-target-arch

Note: This command is for generating an arm64 compatible snap. In the case the user, wants to create an amd64 snap just change arm64 with arm64

Create snap commandCreate snap command

  • Once the snap has been built, the file will be visible in the project folder:

Generated snap Generated snap

  • Clean the directory using the "snapcraft clean --destructive-mode" command:
snapcraft clean --destructive-mode

Clean snap creation foldersClean snap creation folders

Overall explanation

This snap consists of two basic programs:

  1. Python program (main.py). This program is located in the main project folder and it creates the Flask webserver so that the user can interact with the internal directories and files. Additionally, it also gives the option to easily upload files or create new directories in the snap active configuration folder.
  2. Shell script (run.sh). This script is located in the configs folder and it has the purpose to copy some internal files from the project folder to the active configuration folder when the app is installed. It creates a folder in the active configuration and checks the availability of one of the files that should be there, and in the case it is not there, it copies the "Example" file to that folder. This script is in this tutorial just to show that it is possible to copy files during the snap installation, but if the user does not require this functionality and wants to add files later, this shell script is not necessary.
main.py

To be able to run this Python program, some dependencies are necessary. Additionally, it is required to define the snapcraft configuration files correctly to download and include the required modules in the final snap along with the installation. Two folders are required to run correctly the webserver:

  1. static: this folder contains files of static elements of the webserver. In the case the website contains static elements such as images, it is mandatory to define this folder to be able to create the Flask webserver correctly. In this case, only an image is used, but in the case the user does not want to include any image or there is no static element, this folder is not mandatory to be able to run Flask.
  2. templates: this is the most important folder because it contains the html file for creating the webserver. How the website is designed and how all the dynamic elements interact between the Python program and the webserver are defined in this file. 

On the other hand, the main.py file is almost self explanatory due to all the comments provided in the code. At the beginning, it imports all the required modules to run the program, it creates a variable with the general path to the active configuration folder and defines the Flask program. The rest of the code basically consists of 6 sections with the following purposes:

  1. Initial website. This function returns the index.html file to shows the initial website. First it checks the folders, subdirectories and files located in the general path to provide the user a general overview of what is inside the active configuration folder. Additionally, the function returns all these folders, files and subdirectories to visualize them in the website.
  2. Create new directory. As the name says, this function just reads what the user has entered in the website so that it can create a new directory with the makedirs function of the os module. 
  3. Delete directory. Similar to what the the previous function does, this function reads what directory the user enters in the website, and deletes the directory with the rmtree function of the shutil module. 
  4. Upload file. This function used the files and form functions of the request module to get the file that the user wants to upload and in which directory wants to put the selected file. Once all this information has been got, with the save function, the file is stored.
  5. Delete file. As the name says, this function is used to delete files located in the active configuration folder. To achieve this, the remove function from the os module is used.
  6. Flask initialization. There are many possibilities, but in this case, debug has been activated, host has been defined so that it automatically takes the ctrlX CORE IP address and the 8001 port has been selected. 

In the case the user wants to add some functionalities to the webserver or wants to understand better how the program works, please check the official Flask module.

To be able to run correctly this Python program, it is necessary to configure the yaml and setup.py files. 

  • setup.py. In this file, the folders the main.py needs to be able to work, are defined so that when the snap is built they are included. On the other hand, the required Flask module is also defined so that, when the snap is built, the module is downloaded and included in the final snap. Additionally, the script, version, licence and other things are defined.
  • snapcraft.yaml. There are different sections that has to be considered to be able to correctly run the Python program:

To correctly run the main.py it is required to define its location when the snap is built, which plugs it needs and when it is started. All this is defined in the apps section inside the yaml file:

apps:
  active:
    command: bin/main.py
    plugs:
      - network
      - network-bind
      - active-solution                                 
    daemon: simple
    passthrough:
      restart-condition: always
      restart-delay: 10s

In the parts section, the location inside the project folder of the Python program is defined and which plugin has to be used:

parts:
  active:
    plugin: python
    source: .
Additionally, the dependencies folder is copied from the project folder to the bin folder of the final snap using the dump plugin:
  flask-dependencies:
    source: .
    plugin: dump
    organize:
      'dependencies/*': bin/
run.sh 
For this shell script, it is just required to correctly define the snapcraft.yaml file. In the apps section, the location of the script, the command that has to be executed and the required plugs are defined:
apps: 
activeconfiguration:
    command: ./bin/run.sh
    daemon: simple
    plugs: [network, network-bind, active-solution]
Active configuration access
In addition to correctly define the location, plugins, commands of the two programs that work in the background, it is necessary to give to the snap access to the active configuration folder in the ctrlX CORE. For that purpose, the following actions are required to do:
On the snapcraft.yaml file, the following lines have to be added:
  • On the parts section it is required to add the following lines:
parts:
    activeconfiguration:
        source: ./configs/  
        plugin: dump
        organize:
          '*': bin/
  • On the hooks section it is required to add the following lines:
hooks:     
    connect-plug-active-solution:  
        plugs: [active-solution]
  • On the plugs section these lines:
plugs:  
    active-solution:  
        interface: content
        content: solutions
        target: $SNAP_COMMON/solutions
Note: on the apps section make sure that the active-solution plug is included:
apps:
  active:
    command: bin/main.py
    plugs:
      - network
      - network-bind
      - active-solution                                 #<--------------------------------------------
    daemon: simple
    passthrough:
      restart-condition: always
      restart-delay: 10s

  activeconfiguration:
    command: ./bin/run.sh
    daemon: simple
    plugs: [network, network-bind, active-solution]     #<--------------------------------------------
 
  • On the snap/hooks/connect-plug-active-solution:

This file creates an active folder in the active configuration folder in the ctrlX CORE.

ctrlX CORE interface

In this section it will be shown how to create the menus and sidebars in the ctrlX CORE interface to be able to access to the webserver. To be able to define this, the novnc.package-manifest.json file is used. This file is located in the configs/package-assets folders.

Additionally, it is required to tell to the snapcraft.yaml file that copies this file to the final snap:

parts:
  configs:     
    source: ./configs
    plugin: dump   
    organize:
      'package-assets/*': package-assets/${SNAPCRAFT_PROJECT_NAME}/
On the other hand, in the slots section it is also required to write some lines of code to correctly integrate this to the ctrlX CORE interface:
slots:
    package-assets:        
        interface: content
        content: package-assets
        source:
            read:
            - $SNAP/package-assets/${SNAPCRAFT_PROJECT_NAME}
    package-run:
        interface: content
        content: package-run
        source:
            write:
            - $SNAP_DATA/package-run/${SNAPCRAFT_PROJECT_NAME}
sanX
sanX
Hi, I am Nicolas from the DCEM Application Team. I am temporary not available, if you have any questions, do not hesitate to contact LunatiX.
Must Read
Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist