MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.

    MMM-config with modules that have sub-configs (MMM-TouchButton)

    Scheduled Pinned Locked Moved Solved Troubleshooting
    10 Posts 3 Posters 1.0k Views 3 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J Offline
      joey
      last edited by

      I have recently started using MMM-config. I was unable to determine how to use it with modules that have sub-configs or that it is unaware of, such as MMM-TouchButton.

      MMM-TouchButton requires buttons to be defined in the config, but each button has a sub-config with the information about the individual button (such as icon, command/action, etc). By itself, this would not be a huge problem since I have been using MM for years prior to cool new tools like MMM-config. The problem happens when it appears that MMM-config clobbers configs that it did not create, or maybe just configs that it is not aware of (such as these MMM-TouchButton sub-configs).

      Since I am new to MMM-config, I may have done something wrong somewhere along the way.

      Example of MMM-TouchButton config (entered manually):

      module: "MMM-TouchButton",
              position: "top_left",
                config: {
                  buttons: [
                    {
                      name: "Suspend",
                      icon: "fa fa-pause",
                      command: "/usr/bin/systemctl",
                      args: "suspend",
                    },
                  ]
              },
      

      Config for MMM-TouchButton after going into MMM-config to change an unrelated setting (such as switching the default clock module from 12-hour time to 24-hour time) without even touching/expanding the MMM-TouchButton settings:

            {
              module: "MMM-TouchButton",
              position: "top_left",
              config: {
                buttons: [
                  "[object Object]"
                ]
              },
              disabled: false,
              hiddenOnStartup: false,
              configDeepMerge: false,
              order: "*",
              animateIn: "None",
              animateOut: "None"
            },
      
      S 1 Reply Last reply Reply Quote 0
      • J Offline
        joey
        last edited by

        Wow, that is great! I was just hoping for it to not reset the module settings. Being able to add the module-specific details is definitely useful. That you and Tom worked the rest of it out between my first post and now is even more amazing!

        I set up my MagicMirror, but then leave it alone for a long time. I typically only touch it when an OS or MM update causes an issue. Looking back now, the entire setup process is so much better than it has ever been before!

        Thank you for all the ways that MM has become easier and easier. (And thanks to Tom for adding the schema file!)

        I meant to add a link to the module that started this discussion, since it has been useful to me: https://github.com/Tom-Hirschberger/MMM-TouchButton I mainly use it for shutdown/sleep/reboot functions, but it is a great way to be able to run an arbitrary command for an MM running on a touchscreen (or by opening the MM page from a different device and clicking the TouchButton).

        S wishmaster270W 3 Replies Last reply Reply Quote 0
        • S Offline
          sdetweil @joey
          last edited by sdetweil

          @joey yes, in JS there are no defined structures.
          so in this case the code doesn’t match the doc

            defaults: {
              animationSpeed: 0,
              classes: null,
              buttons: [],
              addEmptyTitle: false,
              refreshOnNotification: true,
              refreshOnlyIfValueChanged: true,
              notificationDelay: 3000,
              notificationsAtStart: []
            },
          

          buttons is an array []
          but we don’t know what is supposed to be INSIDE it (strings, numbers objects???)

          MMM-Config has to ‘discover’ the variables used by the module and make assumptions when its not clear

          BUT the author (or any user) could create a customized form definition for a module so that it could be clearer and more usable

          the MMM-Config wiki describes the different choices for this work .

          temporarily I added all the variables defined in the doc
          then started MM so it generated the definitions file
          then i used the

          create_form_for_module.sh MMM-TouchButton
          

          command to create the custom form file
          then restored the original MMM-TouchButton.js
          in the module folder

          git checkout MMM-TouchButton.js 
          

          then edited and made some things selection lists vs text entry

          create this file in the MMM-TouchButton folder
          MMM-Config.schema.json
          with this contents

          {
            "schema": {
              "MMM-TouchButton": {
                "type": "object",
                "title": "properties for MMM-TouchButton",
                "properties": {
                  "module": {
                    "type": "string",
                    "title": "module",
                    "default": "MMM-TouchButton",
                    "readonly": true
                  },
                  "disabled": {
                    "type": "boolean",
                    "title": "disabled",
                    "default": false
                  },
                  "position": {
                    "type": "string",
                    "title": "module position",
                    "readonly": "true"
                  },
                  "classes": {
                    "type": "string",
                    "title": "classes",
                    "default": ""
                  },
                  "header": {
                    "type": "string",
                    "title": "header",
                    "default": ""
                  },
                  "hiddenOnStartup": {
                    "type": "boolean",
                    "title": "hiddenOnStartup",
                    "default": false
                  },
                  "configDeepMerge": {
                    "type": "boolean",
                    "title": "configDeepMerge",
                    "default": false
                  },
                  "order": {
                    "type": "string",
                    "title": "order",
                    "default": "*"
                  },
                  "inconfig": {
                    "type": "string",
                    "title": "inconfig",
                    "default": "0"
                  },
                  "index": {
                    "type": "integer"
                  },
                  "animateIn": {
                    "type": "string",
                    "enum": [
                      "None",
                      "bounce",
                      "flash",
                      "pulse",
                      "rubberBand",
                      "shakeX",
                      "shakeY",
                      "headShake",
                      "swing",
                      "tada",
                      "wobble",
                      "jello",
                      "heartBeat",
                      "backInDown",
                      "backInLeft",
                      "backInRight",
                      "backInUp",
                      "bounceIn",
                      "bounceInDown",
                      "bounceInLeft",
                      "bounceInRight",
                      "bounceInUp",
                      "fadeIn",
                      "fadeInDown",
                      "fadeInDownBig",
                      "fadeInLeft",
                      "fadeInLeftBig",
                      "fadeInRight",
                      "fadeInRightBig",
                      "fadeInUp",
                      "fadeInUpBig",
                      "fadeInTopLeft",
                      "fadeInTopRight",
                      "fadeInBottomLeft",
                      "fadeInBottomRight",
                      "flip",
                      "flipInX",
                      "flipInY",
                      "lightSpeedInRight",
                      "lightSpeedInLeft",
                      "rotateIn",
                      "rotateInDownLeft",
                      "rotateInDownRight",
                      "rotateInUpLeft",
                      "rotateInUpRight",
                      "jackInTheBox",
                      "rollIn",
                      "zoomIn",
                      "zoomInDown",
                      "zoomInLeft",
                      "zoomInRight",
                      "zoomInUp",
                      "slideInDown",
                      "slideInLeft",
                      "slideInRight",
                      "slideInUp"
                    ]
                  },
                  "animateOut": {
                    "type": "string",
                    "enum": [
                      "None",
                      "backOutDown",
                      "backOutLeft",
                      "backOutRight",
                      "backOutUp",
                      "bounceOut",
                      "bounceOutDown",
                      "bounceOutLeft",
                      "bounceOutRight",
                      "bounceOutUp",
                      "fadeOut",
                      "fadeOutDown",
                      "fadeOutDownBig",
                      "fadeOutLeft",
                      "fadeOutLeftBig",
                      "fadeOutRight",
                      "fadeOutRightBig",
                      "fadeOutUp",
                      "fadeOutUpBig",
                      "fadeOutTopLeft",
                      "fadeOutTopRight",
                      "fadeOutBottomRight",
                      "fadeOutBottomLeft",
                      "flipOutX",
                      "flipOutY",
                      "lightSpeedOutRight",
                      "lightSpeedOutLeft",
                      "rotateOut",
                      "rotateOutDownLeft",
                      "rotateOutDownRight",
                      "rotateOutUpLeft",
                      "rotateOutUpRight",
                      "hinge",
                      "rollOut",
                      "zoomOut",
                      "zoomOutDown",
                      "zoomOutLeft",
                      "zoomOutRight",
                      "zoomOutUp",
                      "slideOutDown",
                      "slideOutLeft",
                      "slideOutRight",
                      "slideOutUp"
                    ]
                  },
                  "config": {
                    "type": "object",
                    "title": "config",
                    "properties": {
                      "animationSpeed": {
                        "type": "integer"
                      },
                      "classes": {
                        "type": "string"
                      },
                      "buttons": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "icon": {
                              "type": "string"
                            },
                            "imgIcon": {
                              "type": "string"
                            },
                            "command": {
                              "type": "string"
                            },
                            "args": {
                              "type": "string"
                            },
                            "title": {
                              "type": "string"
                            },
                            "notification": {
                              "type": "string"
                            },
                            "payload": {
                              "type": "object",
                              "properties": {
                                "type": {
                                  "type": "string"
                                },
                                "payload": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "profiles": {
                              "type": "string"
                            },
                            "classes": {
                              "type": "string"
                            },
                            "conditions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "source": {
                                    "type": "string",
                                    "enum":[
                                      "out",
                                      "err",
                                      "code"
                                    ]
                                  },
                                  "type": {
                                    "type": "string",
                                    "enum":[
                                      "lt",
                                      "le",
                                      "gt",
                                      "ge",
                                      "eq",
                                      "incl",
                                      "mt"
                                    ]
                                  },
                                  "value": {
                                    "type": "string"
                                  },
                                  "icon": {
                                    "type": "string"
                                  },
                                  "jsonpath": {
                                    "type": "string"
                                  },
                                  "imgIcon": {
                                    "type": "string"
                                  },
                                  "classes": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      },
                      "addEmptyTitle": {
                        "type": "boolean"
                      },
                      "refreshOnNotification": {
                        "type": "boolean"
                      },
                      "refreshOnlyIfValueChanged": {
                        "type": "boolean"
                      },
                      "notificationDelay": {
                        "type": "integer"
                      },
                      "notificationsAtStart": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            },
            "form": [
              {
                "key": "MMM-TouchButton.disabled",
                "htmlClass": "disabled_checkbox",
                "description": "when checked the module will not be used by MagicMirror<br> but will remain in config.js if already present"
              },
              {
                "key": "MMM-TouchButton.position",
                "description": "use Module Positions section below to set or change"
              },
              {
                "key": "MMM-TouchButton.header",
                "description": "header to use for this module"
              },
              {
                "key": "MMM-TouchButton.hiddenOnStartup",
                "description": "Set module as being hidden on startup. This field is optional."
              },
              {
                "key": "MMM-TouchButton.configDeepMerge",
                "description": "Allow to merge with internal configuration in deep"
              },
              {
                "key": "MMM-TouchButton.classes",
                "description": "css classes to use for this module, beyond what MM provides"
              },
              {
                "key": "MMM-TouchButton.order",
                "type": "hidden"
              },
              {
                "key": "MMM-TouchButton.inconfig",
                "type": "hidden"
              },
              {
                "key": "MMM-TouchButton.animateIn",
                "title": "animateIn",
                "description": "select one of these to change the behavior when the module is shown"
              },
              {
                "key": "MMM-TouchButton.animateOut",
                "title": "animateOut",
                "description": "select one of these to change the behavior when the module is hidden"
              },
              {
                "key": "MMM-TouchButton.index",
                "type": "hidden"
              },
              {
                "type": "fieldset",
                "title": "config",
                "htmlClass": "moduleConfig",
                "items": [
                  {
                    "type": "button",
                    "title": "Open module readme",
                    "htmlClass": "repo_button",
                    "onClick": "(evt,node)=>{let siblings=$(evt.target).siblings('.readme_url');let element=siblings.toArray()[0];let url=element.innerText;let pos=$(evt.target).offset();process_readme(url,pos)}"
                  },
                  {
                    "type": "button",
                    "htmlClass": "hidden readme_url",
                    "title": "http://localhost:xxxx/modules/MMM-TouchButton/README.md"
                  },
                  {
                    "title": "animationSpeed",
                    "key": "MMM-TouchButton.config.animationSpeed"
                  },
                  {
                    "title": "classes",
                    "key": "MMM-TouchButton.config.classes"
                  },
                  {
                    "type": "array",
                    "title": "buttons",
                    "deleteCurrent": false,
                    "items": {
                      "type": "fieldset",
                      "title": "buttons",
                      "items": [
                        {
                          "title": "name",
                          "key": "MMM-TouchButton.config.buttons[].name"
                        },
                        {
                          "title": "icon",
                          "key": "MMM-TouchButton.config.buttons[].icon"
                        },
                        {
                          "title": "imgIcon",
                          "key": "MMM-TouchButton.config.buttons[].imgIcon"
                        },
                        {
                          "title": "command",
                          "key": "MMM-TouchButton.config.buttons[].command"
                        },
                        {
                          "title": "args",
                          "key": "MMM-TouchButton.config.buttons[].args"
                        },
                        {
                          "title": "title",
                          "key": "MMM-TouchButton.config.buttons[].title"
                        },
                        {
                          "title": "notification",
                          "key": "MMM-TouchButton.config.buttons[].notification"
                        },
                        {
                          "type": "fieldset",
                          "title": "payload",
                          "items": [
                            {
                              "title": "type",
                              "key": "MMM-TouchButton.config.buttons[].payload.type"
                            },
                            {
                              "type": "array",
                              "title": "payload",
                              "deleteCurrent": false,
                              "items": [
                                {
                                  "title": "payload {{idx}}",
                                  "key": "MMM-TouchButton.config.buttons[].payload.payload[]",
                                  "type": "ace",
                                  "aceMode": "json",
                                  "aceTheme": "twilight",
                                  "width": "100%",
                                  "height": "100px"
                                }
                              ]
                            }
                          ]
                        },
                        {
                          "title": "profiles",
                          "key": "MMM-TouchButton.config.buttons[].profiles"
                        },
                        {
                          "title": "classes",
                          "key": "MMM-TouchButton.config.buttons[].classes"
                        },
                        {
                          "type": "array",
                          "title": "conditions",
                          "deleteCurrent": false,
                          "items": {
                            "type": "fieldset",
                            "title": "conditions",
                            "items": [
                              {
                                "title": "source",
                                "key": "MMM-TouchButton.config.buttons[].conditions[].source"
                              },
                              {
                                "title": "type",
                                "key": "MMM-TouchButton.config.buttons[].conditions[].type"
                              },
                              {
                                "title": "value",
                                "key": "MMM-TouchButton.config.buttons[].conditions[].value"
                              },
                              {
                                "title": "icon",
                                "key": "MMM-TouchButton.config.buttons[].conditions[].icon"
                              },
                              {
                                "title": "jsonpath",
                                "key": "MMM-TouchButton.config.buttons[].conditions[].jsonpath"
                              },
                              {
                                "title": "imgIcon",
                                "key": "MMM-TouchButton.config.buttons[].conditions[].imgIcon"
                              },
                              {
                                "title": "classes",
                                "key": "MMM-TouchButton.config.buttons[].conditions[].classes"
                              }
                            ]
                          }
                        }
                      ]
                    },
                    "draggable": false
                  },
                  {
                    "title": "addEmptyTitle",
                    "key": "MMM-TouchButton.config.addEmptyTitle"
                  },
                  {
                    "title": "refreshOnNotification",
                    "key": "MMM-TouchButton.config.refreshOnNotification"
                  },
                  {
                    "title": "refreshOnlyIfValueChanged",
                    "key": "MMM-TouchButton.config.refreshOnlyIfValueChanged"
                  },
                  {
                    "title": "notificationDelay",
                    "key": "MMM-TouchButton.config.notificationDelay"
                  },
                  {
                    "type": "array",
                    "title": "notificationsAtStart",
                    "deleteCurrent": false,
                    "items": [
                      {
                        "title": "notificationsAtStart {{idx}}",
                        "key": "MMM-TouchButton.config.notificationsAtStart[]"
                      }
                    ]
                  }
                ]
              }
            ],
            "value": {
              "disabled": true,
              "module": "MMM-TouchButton",
              "position": "none",
              "order": "*",
              "inconfig": "0",
              "config": {
                "animationSpeed": 0,
                "classes": null,
                "buttons": [
                  {
                    "name": "",
                    "icon": "",
                    "imgIcon": null,
                    "command": "",
                    "args": "",
                    "title": null,
                    "notification": "",
                    "payload": {
                      "type": "",
                      "payload": {}
                    },
                    "profiles": null,
                    "classes": null,
                    "conditions": [
                    ]
                  }
                ],
                "addEmptyTitle": false,
                "refreshOnNotification": true,
                "refreshOnlyIfValueChanged": true,
                "notificationDelay": 3000,
                "notificationsAtStart": []
              },
              "animateIn": "none",
              "animateOut": "none"
            }
          }
          

          its not everything that can be done…
          headings can be changed,
          help can be added
          etc…

          Sam

          How to add modules

          learning how to use browser developers window for css changes

          S 1 Reply Last reply Reply Quote 0
          • S Offline
            sdetweil @sdetweil
            last edited by

            i submitted this to the module

            Sam

            How to add modules

            learning how to use browser developers window for css changes

            S 1 Reply Last reply Reply Quote 0
            • S Offline
              sdetweil @sdetweil
              last edited by

              Tom added the schema file to the module package for future users

              Sam

              How to add modules

              learning how to use browser developers window for css changes

              1 Reply Last reply Reply Quote 0
              • J Offline
                joey
                last edited by

                Wow, that is great! I was just hoping for it to not reset the module settings. Being able to add the module-specific details is definitely useful. That you and Tom worked the rest of it out between my first post and now is even more amazing!

                I set up my MagicMirror, but then leave it alone for a long time. I typically only touch it when an OS or MM update causes an issue. Looking back now, the entire setup process is so much better than it has ever been before!

                Thank you for all the ways that MM has become easier and easier. (And thanks to Tom for adding the schema file!)

                I meant to add a link to the module that started this discussion, since it has been useful to me: https://github.com/Tom-Hirschberger/MMM-TouchButton I mainly use it for shutdown/sleep/reboot functions, but it is a great way to be able to run an arbitrary command for an MM running on a touchscreen (or by opening the MM page from a different device and clicking the TouchButton).

                S wishmaster270W 3 Replies Last reply Reply Quote 0
                • S Offline
                  sdetweil @joey
                  last edited by

                  @joey we are still discussing how to properly support his conditions settings, so there will be an update when we figure it out

                  the form library makes a lot of these things simple
                  add an enum to the string definition and now you get a select list, so a user cant put in the wrong thing, no spelling errors…

                  Sam

                  How to add modules

                  learning how to use browser developers window for css changes

                  1 Reply Last reply Reply Quote 0
                  • S Offline
                    sdetweil @joey
                    last edited by

                    @joey make sure you backup, backup , backup

                    my backup/restore scripts on top of install/update
                    can give you a lot of security and safety

                    Sam

                    How to add modules

                    learning how to use browser developers window for css changes

                    J 1 Reply Last reply Reply Quote 0
                    • wishmaster270W Offline
                      wishmaster270 Module Developer @joey
                      last edited by wishmaster270

                      @joey Great you like the module.
                      Just to clear out some things.

                      Most of the work did Sam not me. I only hit the merge button. So big thank you to him.

                      1 Reply Last reply Reply Quote 0
                      • J Offline
                        joey @sdetweil
                        last edited by

                        @sdetweil said in MMM-config with modules that have sub-configs (MMM-TouchButton):

                        @joey make sure you backup, backup , backup

                        my backup/restore scripts on top of install/update
                        can give you a lot of security and safety

                        I should probably look into that. Currently, I just copy the entire directory to another place on the MM system (in case of an issue with upgrade or messing up the config), and I copy the config.js file to another system (in case of an OS/hardware issue – I use a LOT of old hardware). Up until now, I have mainly taken an OS/hardware failure as an opportunity to try a new flavor of Linux and investigate new modules while setting up MM from scratch again!

                        I am setting up a new one (brand new laptop with a manufacture date of only 12 years ago!) and it is a great opportunity to look into a proper backup with your scripts.

                        S 1 Reply Last reply Reply Quote 0
                        • S Offline
                          sdetweil @joey
                          last edited by

                          @joey the backup approach gives you the ability to restore the modules and config/css to another system , after install, so you get a migration tool

                          AND it provides git versioning… so if you need to go back 2 revs you can
                          it also supports putting the backup on a (private recommended) github repo, so you can restore directly from there and don’t have any local file system failure issues… disk drives, usb sticks, etc
                          AND it doesn’t matter WHERE you are at the time,

                          Sam

                          How to add modules

                          learning how to use browser developers window for css changes

                          1 Reply Last reply Reply Quote 0
                          • S sdetweil has marked this topic as solved
                          • 1 / 1
                          • First post
                            Last post
                          Enjoying MagicMirror? Please consider a donation!
                          MagicMirror created by Michael Teeuw.
                          Forum managed by Sam, technical setup by Karsten.
                          This forum is using NodeBB as its core | Contributors
                          Contact | Privacy Policy