• Categories
  • Recent
  • Tags
  • Popular
  • Register
  • Login
  • Categories
  • Recent
  • Tags
  • Popular
  • Register
  • Login

custom widget: send command to node

Scheduled Pinned Locked Moved Dashboard
21 Posts 4 Posters 5.1k Views 2 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.
  • E Offline
    elgarfo
    last edited by 9 Dec 2018, 17:14

    hi,

    i have read the "widget - sensor custom buttons", "rgb controller", "custom widget" and "custom widget - dynamic images on dashboard" topics but did only get a hint on what to do.

    what i have:
    a custom widget with a nice, touch enabled color picker, which is working. which means:

    • can be displayed on the dashboard
    • and is usable
    • and javascript events are fired (currently logs a rgb hex value to browser console)
    • using: iro.js

    what i want:

    • send the selected rgb hex value to a node

    i saw a mention to create a custom angular controller and plug that into Utilities > HTML additional headers > AngularJS custom controllers.
    can anyone provide an example of a angularjs controller to put there?

    i tried to use Utilities > Scripts like in the example "Custom widget" but the variables defined there do not seem to be accessible in the Templates. at least i was unable to use it to send a value to the node.

    so... i am currently stuck.
    is there any documentation (other than plowing through mycontrollers code) which describes how to add a custom widget which can send a value to a node generated in js? i know its possible to send a value using the Utilities > Scripts but this is rather static, as the script only runs during widget creation. which means it only runs on opening the dashboard and if i change the color-picker by touching/clicking it, i can not push the value to a node.

    J 1 Reply Last reply 10 Dec 2018, 05:51 Reply Quote 0
    • J Offline
      jkandasa @elgarfo
      last edited by 10 Dec 2018, 05:51

      @elgarfo Yes, It is possible to add your custom controller in Utilities > HTML additional headers > AngularJS custom controllers. can you share your current work, I can extend from there?

      1 Reply Last reply Reply Quote 0
      • E Offline
        elgarfo
        last edited by 10 Dec 2018, 16:46

        @jkandasa, thanks for helping me out.

        currently i have this as template:

        <style type="text/css">
        .wrap {
          color: #fff;
          background: #171F30;
          margin: 0 auto;
          display: flex;
          flex-direction: row;
          align-items: center;
          justify-content: center;
        }
        </style>
        <div class="wrap">
          <div class="colorPicker"></div>
        </div>
        <script>
        var colorPicker = new iro.ColorPicker(".colorPicker", {
          width: 320,
          height: 320,
          color: {r: 255, g: 0, b: 0},
          anticlockwise: true,
          borderWidth: 1,
          borderColor: "#fff",
        });
        
        colorPicker.on("color:change", function(color) {
          console.log("hex: " + color.hexString);
        });
        </script>
        

        and this for the script:

        var colorSensor = mcApi.uidTag().getByUid("hi-wz-rgb-1").getResource();
        var uuid = mcApi.utils().getUUID();
        

        i tried to copy the "Sensors" controller from github modify it to make for a "Sensors2" controller an pasted that into the "AngularJS custom controllers":

        'use strict';
        
        angular.module('adf.widget.myc-sen-vars2', [])
          .config(function(dashboardProvider){
            dashboardProvider
              .widget('mycSenVars2', {
                title: 'Sensors2',
                description: 'Monitor and change sensors state',
                templateUrl: 'controllers/adf-widgets/adf-myc-sen-vars/view.html?mcv=${mc.gui.version}',
                controller: 'mycSenVarsController2',
                controllerAs: 'mycSenVars2',
                config: {
                  variableIds:[],
                  showIcon: true,
                  itemsPerRow:"2",
                  refreshTime:30,
                },
                edit: {
                  templateUrl: 'controllers/adf-widgets/adf-myc-sen-vars/edit.html?mcv=${mc.gui.version}',
                  controller: 'mycSenVarsEditController2',
                  controllerAs: 'mycSenVarsEdit2',
                }
              });
          })
          .controller('mycSenVarsController2', function($scope, $interval, config, mchelper, $filter, SensorsFactory, TypesFactory, CommonServices){
            var mycSenVars2 = this;
        
            mycSenVars2.showLoading = true;
            mycSenVars2.isSyncing = true;
            mycSenVars2.variables = {};
            $scope.tooltipEnabled = false;
            $scope.hideVariableName= !config.showIcon;
            $scope.cs = CommonServices;
        
            //HVAC heater options - HVAC flow state
            $scope.hvacOptionsFlowState = TypesFactory.getHvacOptionsFlowState();
            //HVAC heater options - HVAC flow mode
            $scope.hvacOptionsFlowMode = TypesFactory.getHvacOptionsFlowMode();
            //HVAC heater options - HVAC fan speed
            $scope.hvacOptionsFanSpeed = TypesFactory.getHvacOptionsFanSpeed();
        
            //Defined variable types list
            $scope.definedVariableTypes = CommonServices.getSensorVariablesKnownList();
        
        
        
          //update rgba color
          $scope.updateRgba = function(variable){
            variable.value = CommonServices.rgba2hex(variable.rgba);
            $scope.updateVariable(variable);
          };
        
            function loadVariables(){
              mycSenVars2.isSyncing = true;
              SensorsFactory.getVariables({'ids':config.variableIds}, function(response){
                  mycSenVars2.variables = response;
                  mycSenVars2.isSyncing = false;
                  if(mycSenVars2.showLoading){
                    mycSenVars2.showLoading = false;
                  }
              });
            };
        
            function updateVariables(){
              if(mycSenVars2.isSyncing){
                return;
              }else if(config.variableIds.length > 0){
                loadVariables();
              }
            }
        
            //load variables initially
            loadVariables();
            //updateVariables();
        
            //Update Variable / Send Payload
            $scope.updateVariable = function(variable){
              SensorsFactory.updateVariable(variable, function(){
                //update Success
              },function(error){
                displayRestError.display(error);
              });
            };
        
            // refresh every second
            var promise = $interval(updateVariables, config.refreshTime*1000);
        
            // cancel interval on scope destroy
            $scope.$on('$destroy', function(){
              $interval.cancel(promise);
            });
          }).controller('mycSenVarsEditController2', function($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices){
            var mycSenVarsEdit2 = this;
            mycSenVarsEdit2.cs = CommonServices;
            mycSenVarsEdit2.variables = TypesFactory.getSensorVariables();
          });
        

        but this does not show up at all in the dashboard.

        that's why i am asking for a simple example for a custom angular controller as i am not too familiar with angular yet.

        J 1 Reply Last reply 11 Dec 2018, 05:51 Reply Quote 0
        • J Offline
          jkandasa @elgarfo
          last edited by 11 Dec 2018, 05:51

          @elgarfo Thanks for the script. Looks like iro.js do not have angular support 😞
          For two way binding, we need angularJS support.

          1 Reply Last reply Reply Quote 0
          • E Offline
            elgarfo
            last edited by 11 Dec 2018, 07:42

            @jkandasa ok thats a little sad. but this will not stop me from trying 🙂

            lets say i wanted to write a custom widget (lets also assume something simple like an html5 slider/range input)

            template:

            <input id="slider1" type="range" min="0" max="100" />
            <script type="text/javascript">
              $('#slider1').on('change', function(e) {
                console.log('slider1 value: '  + $(this).val());
              });
            </script>
            

            script:

            var stepperMotor = mcApi.uidTag().getByUid("hi-wz-blinds-1").getResource();
            var uuid = mcApi.utils().getUUID();
            

            as far as i can tell, this is a pretty basic example which does not rely on incompatible external libs. what do i need to add to which section to make this a widget with two-way binding?

            all i am looking for is an example for a custom 2 way widget.

            J 1 Reply Last reply 11 Dec 2018, 12:17 Reply Quote 0
            • J Offline
              jkandasa @elgarfo
              last edited by jkandasa 12 Nov 2018, 17:48 11 Dec 2018, 12:17

              @elgarfo I do not know how to do with HTML 5. however I made a two-way widget with the angular slider.

              Steps:

              • create HTML template with sensor variable id
              • create dummy javascript to supply buildings
              • add custom css and js files.
              • add custom controller
              • add dependency module in angular (workaround, I do not find a way to include new modules into the controller creation)

              HTML template:

              <div ng-controller="myCustomWidgetController" ng-init="sVariable.id=${sId};loadVariable();">
                <rzslider rz-slider-model="sVariable.value" rz-slider-options="slider.options"></rzslider>
              </div>
              

              Dummy JavaScript:

              // dummy script
              

              9de831a0-816c-4f94-8285-6e427c01b480-image.png

              CSS and JS file:

              https://cdnjs.cloudflare.com/ajax/libs/angularjs-slider/6.6.0/rzslider.min.css
              https://cdnjs.cloudflare.com/ajax/libs/angularjs-slider/6.6.0/rzslider.min.js
              

              52843ff4-392c-4de7-8132-887af7ae6b13-image.png

              Custom controller:

              myControllerModule.controller('myCustomWidgetController', function($scope, SensorsFactory){
                  $scope.sVariable = {
                    id: null,
                    value:null
                  };
                
                  $scope.loadVariable = function(){
                    SensorsFactory.getVariable({id:$scope.sVariable.id}, function(response){
                      if(response.value != undefined){
                        $scope.sVariable.value = parseInt(response.value);
                      }
                    });
                  }
              
                  $scope.slider = {
                    options: {
                      floor: 0,
                      ceil: 100,
                      step: 1,
                      minLimit: 0,
                      maxLimit: 90,
                      onEnd: function() {
                          $scope.sendPayload($scope.sVariable);
                      },
                    }
                };
              
                  // send payload
                  $scope.sendPayload = function(sVariable){
                    SensorsFactory.updateVariable(sVariable, function(){
                      //update Success
                    },function(error){
                      displayRestError.display(error);
                    });
                  };
                });
              

              Workaround, add a module on the app level

              File: mycontroller/www/app.js

              rzModule
              

              f53f954f-e081-49d1-a8de-f127ec382950-image.png

              Widget in dashboard

              d933f59c-b34b-4b55-9800-2bfabfbe07a6-image.png

              d67fa588-62c3-415b-ad8b-b3984d9b882b-image.png

              1 Reply Last reply Reply Quote 1
              • E Offline
                elgarfo
                last edited by elgarfo 13 Dec 2018, 15:29

                @jkandasa your support is outstanding 👍
                your example works good and i can use it to build a dashboard to my needs. thank you very very much.

                the reason it took me so long to respond is, that i needed to trace a startup error on my end:
                [$injector:nomod] Module 'rzModule' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.

                symptoms:

                • dashboard not loading correctly ({{ variable }} everywhere, nothing works)
                • angular throwing error about undefined module
                • testing with dev-console on firefox angular.module('rzModule'); yielded no error.
                • rzslider.js was actually loaded

                cause:

                • firefox does not support <link rel="import">
                • the polyfill i pushed to github fb3d0d96 is working but:
                • too late.

                so the polyfill for the import-feature is working, as i am able to load the rzModule after the dashboard html loaded completely and angular tried to load.
                but it is not working fast enough.

                i am currently trying to find a way to either delay angular startup until all imports are handled or to find a better way to include the /_configurations/additional-headers.html

                current workaround: put <script src="https://cdnjs.cloudflare.com/ajax/libs/angularjs-slider/6.6.1/rzslider.js"></script> directly into index.html for firefox 😕

                EDIT:
                html imports are also deprecated in chrome since v70 and will be removed with v73 which is only two versions from now (v71 as of this writing). see: chrome platform status

                J 2 Replies Last reply 14 Dec 2018, 10:51 Reply Quote 1
                • jkandasaJ Offline
                  jkandasa @elgarfo
                  last edited by 14 Dec 2018, 10:51

                  @elgarfo If we change anything in our current implementation, can fix the issue in both firefox and chrome? Any idea?

                  1 Reply Last reply Reply Quote 0
                  • jkandasaJ Offline
                    jkandasa @elgarfo
                    last edited by 18 Dec 2018, 01:02

                    @elgarfo Thank you for the PR https://github.com/mycontroller-org/mycontroller/pull/486

                    1 Reply Last reply Reply Quote 0
                    • W Offline
                      wanvo
                      last edited by 30 Dec 2018, 12:19

                      How can I download the latest SNAPSHOT with this PR?
                      Is this it? Https: //travis-ci.org/mycontroller-org/mycontroller/builds/472109919

                      jkandasaJ 1 Reply Last reply 31 Dec 2018, 08:02 Reply Quote 0
                      • jkandasaJ Offline
                        jkandasa @wanvo
                        last edited by 31 Dec 2018, 08:02

                        @wanvo Compiled and uploaded in SNAPSHOT location.

                        1 Reply Last reply Reply Quote 1
                        • W Offline
                          wanvo
                          last edited by wanvo 1 Jan 2019, 23:05 31 Dec 2018, 11:14

                          @jkandasa Thanx!
                          I checked this widget in Chrome and Firefox, it works great.

                          1 Reply Last reply Reply Quote 1
                          • R Offline
                            RMF69
                            last edited by RMF69 27 Dec 2019, 14:16

                            I'm just testing out various examples to understand how things work, I'm getting

                            Failed at: ${sId}  [in template "unknown" at line 1, column 69]
                            
                            

                            which I assume is from the first line of the html template, its not finding the angularjs custom controller ? I did modify app.js.

                            I'm pretty sure I've done all of the above to get the slider to appear on dashboard, but I must of missed something. I pasted the angularjs custom controller into the text field in HTML additional headers.

                            Any help 🙂 thanks

                            R 1 Reply Last reply 27 Dec 2019, 22:53 Reply Quote 0
                            • R Offline
                              RMF69 @RMF69
                              last edited by RMF69 27 Dec 2019, 22:53

                              @RMF69 To myself... the script binding id mistyped {sId:2}... got the camel case wrong. Slider is now visible but I get 400 error... as I don't have the variable set up correctly which will get updated ? I've created a global variable "sVariable" but I don't think this is right. How do I get the value out of the slider when its value changes ?

                              R 1 Reply Last reply 28 Dec 2019, 12:11 Reply Quote 0
                              • R Offline
                                RMF69 @RMF69
                                last edited by 28 Dec 2019, 12:11

                                @RMF69 Ok looking through code, I understand that its updating a sensor.variabel and that this id is passed in via the script binding {sId:31}... 31 is the id of a sensor S_LIGHT_LEVEL![alt text](Screenshot from 2019-12-28 13-05-08.png
                                I still get 400 bad requests... and

                                ERROR [Acme.Utils.ThreadPool(0)-PooledThread: Acme.Serve.Serve$ServeConnection@1415568e] [org.mycontroller.standalone.api.jaxrs.exception.mappers.ApplicationExceptionMapper:42] ApplicationException,
                                org.jboss.resteasy.spi.ApplicationException: java.lang.NullPointerException
                                

                                I'd love to understand what I've done wrong:)

                                jkandasaJ 1 Reply Last reply 2 Jan 2020, 07:52 Reply Quote 0
                                • jkandasaJ Offline
                                  jkandasa @RMF69
                                  last edited by 2 Jan 2020, 07:52

                                  @RMF69 Can you report your MyController version? and if you modified the script please report your script.

                                  R 1 Reply Last reply 2 Jan 2020, 17:33 Reply Quote 0
                                  • R Offline
                                    RMF69 @jkandasa
                                    last edited by 2 Jan 2020, 17:33

                                    @jkandasa

                                    Thanks, I've got the latest, Version 1.5.0. And I've not changed anything, just the script binding {sId:31} where 31 is the id of a light dimmer virtual sensor... see picture. I took the ID from the url of that page in the picture below.Screenshot_2020-01-02_18-31-18.png

                                    jkandasaJ 1 Reply Last reply 6 Jan 2020, 11:16 Reply Quote 0
                                    • jkandasaJ Offline
                                      jkandasa @RMF69
                                      last edited by jkandasa 1 Jun 2020, 16:46 6 Jan 2020, 11:16

                                      @RMF69 Click on the Edit icon on the Level variable and use the id from the URL.

                                      in version 1.5, you no need to hardcode rzModule on mycontroller/www/app.js. We have an option on UI to update angular modules.
                                      3482e3a0-d2f2-4189-9f3f-2f4ae7750d72-image.png

                                      R 1 Reply Last reply 6 Jan 2020, 12:44 Reply Quote 0
                                      • R Offline
                                        RMF69 @jkandasa
                                        last edited by 6 Jan 2020, 12:44

                                        @jkandasa Thanks for confirming that in 1.5, the hardcoding of rzModule in mycontroller/www/app.js isn't required. However if I remove rzModule then the slider widget isn't displayed.

                                        Still I can't get the example to work...I've got the id from the place you mention, mine is still 31... I've also noticed that the intial value of the sensor->variable isn't populated. I created simple script to update the value

                                        var myImports = new JavaImporter(java.lang, java.util, org.mycontroller.standalone.utils.McUtils);
                                        
                                        with(myImports) {
                                            dimSensor = mcApi.uidTag().getByUid("dimSensor").getResource();
                                            var v = dimSensor.value; //value2/3 etc
                                            dimSensor.setValue(parseInt(v) + 1);
                                            mcApi.sensor().sendPayload(dimSensor);
                                        }
                                        

                                        I insert the following code into "AngularJs custom controllers"

                                        myControllerModule.controller('myCustomWidgetController', function($scope, SensorsFactory){
                                            $scope.sVariable = {
                                              id: null,
                                              value:null
                                            };
                                          
                                            $scope.loadVariable = function(){
                                              SensorsFactory.getVariable({id:$scope.sVariable.id}, function(response){
                                                if(response.value != undefined){
                                                  $scope.sVariable.value = parseInt(response.value);
                                                } 
                                              });
                                            }
                                        
                                            $scope.slider = {
                                              options: {
                                                floor: 0,
                                                ceil: 100,
                                                step: 1,
                                                minLimit: 0,
                                                maxLimit: 90,
                                                onEnd: function() {
                                                    $scope.sendPayload($scope.sVariable);
                                                },
                                              }
                                          };
                                        
                                            // send payload
                                            $scope.sendPayload = function(sVariable){
                                              SensorsFactory.updateVariable(sVariable, function(){
                                                //update Success
                                              },function(error){
                                                displayRestError.display(error);
                                              });
                                            };
                                          });
                                        

                                        Which is just the original example above, no changes... it seems to me that the pointer/reference to the variable I want to have connected to the slider is correct or working, both when the value is initialized on the loadVariable and when updated. But I just can't see what I've done wrong.

                                        jkandasaJ 1 Reply Last reply 6 Jan 2020, 16:04 Reply Quote 0
                                        • jkandasaJ Offline
                                          jkandasa @RMF69
                                          last edited by 6 Jan 2020, 16:04

                                          @RMF69 Do you see any error on the browser console and/or in MyController log file?

                                          R 1 Reply Last reply 7 Jan 2020, 11:45 Reply Quote 0
                                          • First post
                                            Last post

                                          2

                                          Online

                                          618

                                          Users

                                          531

                                          Topics

                                          3.4k

                                          Posts
                                          Copyright © 2015-2025 MyController.org | Contributors | Localization