Ankündigung

Einklappen
Keine Ankündigung bisher.

- √ - Neues Plugin: Google Blockly als visueller Editor für sh.py Logiken

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #16
    Hallo,

    ich habe dein Plugin noch nicht ausprobieren können (war länger unterwegs). Aber schon einmal Danke für deinen Einsatz!
    Auf der Google-Suche nach diesem Thread ("smarthome blockly") bin ich hierauf (http://www.zipato.com/default.aspx?id=26) gestoßen. Ganz ähnlicher Einsatzbereich :-)

    Gruß,
    Hendrik
    Smart home automation system based on cloud technology using zigbee and z-wave devices to provide safe and energy efficient connected home experience.

    Kommentar


      #17
      Hallo,

      hier ein wenig Feedback meinerseits:
      In der blockly_page.html finden sich Verweise nach pages/smarthome. Dieser Pfad kann natürlich beim Nutzer anders sein.
      Ich habe das shblocks in meinen pages-Ordner kopiert. Ich denke, dass dann ein relativer Verweis funktionieren sollte.

      Auch in der __init__.py gibt es eine feste Verdrahtung:
      Code:
          def run(self):
              outdir = self.smartvisu_dir + '/pages/smarthome'
      besser wäre m.M.

      Code:
          def run(self):
              outdir = self.smartvisu_dir
      und dempentsprechend:
      Code:
      [blockly]
          class_name = LogicEditor
          class_path = plugins.logiceditor
          smartvisu_dir = /var/www/html/visu/pages/henfri
      Soviel erstmal zu meinem bescheidenen Feedback. Jetzt muss ich mal weiter schauen.

      Gruß,
      Hendrik

      Kommentar


        #18
        Hallo nochmal,

        leider funktioniert der Logik-Editor noch nicht, trotz obiger Anpassungen.
        Sh.py startet jetzt zwar ohne Fehlermeldungen von blockly, doch sieht die Seite so aus (http://homeserver/visu/index.php?page=blockly_page):blockly.PNG

        Ich bin nicht sicher, ob das noch ein Problem ist, welches damit zusammenhängt, dass scheinbar die Auto-Generierung der Visu vorausgesetzt wird.
        Im Blockly-Item ist ja ein entsprechender String:
        Code:
           
        [blockly]
            name = Blockly Editor Base
            sv_page = blockly_sv_page
            sv_img = status_automatic.svg
        [[xml]]
                type = str
                visu_acl = rw
                sv_widget = "{{ basic.value('item', 'item','','textarea') }}"
            [[python]]
                type = str
                visu_acl = rw
                sv_widget = "{{ basic.value('item', 'item','','textarea') }}"
        Ich verstehe aber nicht, was hier gemacht wird.
        Sollte ich statt der http://homeserver/visu/index.php?page=blockly_page http://homeserver/visu/index.php?page=blockly_sv_page aufrufen (die eben von der Auto-Generation erzeugt würde?)?

        Gruß,
        Hendrik

        Kommentar


          #19
          Hallo,
          diese leere Werkzeugleiste sollte verschwinden, wenn man die Seite über den Browser-Button neu läd. Das ist eines der Probleme, die ich nicht gelöst bekommen habe: beim Anzeigen einer Seite über die Menü-Struktur wird der DOM-Baum nicht richtig aktualisiert. Das ist kein Problem der Auto-Generierung - die wird im Plugin-Code nicht benötigt. Vielmehr wird die die HTML-Seite mit Werkzeugleiste-XML beim Neustart des SH statisch erzeugt und im SV-Verzeichnis abgelegt.
          Schönen Gruß.

          Kommentar


            #20
            NEUSTART - der Blockly-Editor im Backend

            Ich habe mich, wie im anderen Thread angedeutet, mit der Einbindung des Blockly-Editors für Logiken in das neue Backend aus shNG befasst. Das funktioniert soweit.

            Jetzt wäre konzeptionell zu klären, wie Daten (Textdateien, Konfig.-Dateien, allgemein) vom Browser in die Konfiguration des shNG zurück geschrieben werden. Gibt es da bereits Ansätze?
            Im alten Modell hatte ich dies ja als Items im sh eingebaut und per Cache gesichert. Hier würde ich lieber direkt eine XML-Datei wegschreiben.

            Gruß, Dirk
            You do not have permission to view this gallery.
            This gallery has 1 photos.

            Kommentar


              #21
              Wow. Toll!
              Aufbruch Stimmung hier
              Zuletzt geändert von henfri; 13.08.2016, 16:32.

              Kommentar


                #22
                Hallo Dirk.

                Schaut echt schon mal toll aus.
                Wäre der Editor im Backend-Plugin von Version 1.2 bereits drin oder erst in einer späteren Version? - Hoffentlich wird die 1.2 generell bald freigegeben...

                Beste Grüße,
                Markus

                Kommentar


                  #23
                  Ich würde die Dateien direkt per HTTP POST an SH schicken und dann durch das Backend-Plugin speichern. Beim Überschreiben von Dateien die alte Datei mit einer Revisionsnummer am Dateinamen abspeichern.

                  Viele Grüße,
                  Thomas

                  Kommentar


                    #24
                    Erstmal: SAUGEIL!!

                    Leider: Die 1.2 ist Feature Freeze. Ich denke auch, dass wir etwas testen müssen, daher sollte es mit der 1.3 (vermutlich Jahresende) klappen. Wenn das Database Plugin mal so tut wie es soll und mit den ganzen PRs die gerade reinkommen, haben wir fast schon wieder genug Features beisammen.

                    Zum Speichern: aktuell würden wir ja nur Logiken bearbeiten, richtig? Post und Datei speichern in dem Fall, ja. Mehr Konzept gibts dazu leider noch nicht, solange nur das Backend-Plugin so nah an den Dateien ist, kann mans verkraften denke ich.. Alternativ müsste man mal alle in die DB packen so wie bei einem "anderen" Produkt, da bin ich aber kein Fan von.

                    Revisionsnummer bzw. Archivierung ist wichtig, ich würde vor dem Speichern zudem gerne sehen, was für Python-Code rauskommt. Zumindest im "Developer" Modus. Das müsste ja machbar sein?

                    Kommentar


                      #25
                      prove of concept!

                      (x) Trigger: cron
                      ( ) Trigger: watchitem
                      (x) Items
                      (x) save
                      (x) load / undo
                      ( ) clear
                      (x) start (aktivieren)
                      (x) stop (deaktivieren)

                      Revisionsnummer bzw. Archivierung ist wichtig...
                      Ich bin mir nicht sicher, ob das sein muss...

                      ... ich würde vor dem Speichern zudem gerne sehen, was für Python-Code rauskommt. Zumindest im "Developer" Modus. Das müsste ja machbar sein?
                      (x) Python Code Ansicht
                      (x) XML Code Ansicht


                      blockly_backend_002.PNG

                      blockly_backend_003.PNG

                      blockly_backend_004.PNG


                      Code:
                      <!DOCTYPE html>
                      {% extends "base.html" %}
                      {% import "navbar.html" as nav with context %}
                      {% block navbar %}
                          {{ nav }}
                      {% endblock navbar %}
                      
                      {% block content %}
                        <style>
                          li.L0, li.L1, li.L2, li.L3,
                          li.L5, li.L6, li.L7, li.L8
                          { list-style-type: decimal !important }
                        </style>
                       
                       {% include "logics_blockly_toolbox.html" %}
                      
                      
                        <table width="100%" height="100%">
                          <tr>
                            <td>
                              <h1><a href="https://developers.google.com/blockly/">Blockly</a>&rlm; &gt; Logics Editor&rlm;
                              </h1>
                            </td>
                          </tr>
                      
                          <tr>
                            <td colspan=1>
                              <table width="100%">
                                <tr id="tabRow" height="1em">
                                  <td id="tab_blocks" class="tabon">Blocks</td>
                                  <td class="tabmin">&nbsp;</td>
                                  <td id="tab_python" class="taboff">Python</td>
                                  <td class="tabmin">&nbsp;</td>
                                  <td id="tab_xml" class="taboff">XML</td>
                                  <td class="tabmax">
                              <form name="input" action="logics_blockly.html" method="POST" enctype="multipart/form-data">
                            <button onclick="function() {$.ajax({'url': '/logics_blockly_start'})}" class="btn btn-default btn-xs">Activate</button>
                            <button onclick="function() {$.ajax({'url': '/logics_blockly_stop'})}" class="btn btn-default btn-xs">Stop</button>
                            <button onclick="Code.saveBlocks()" class="btn btn-default btn-xs">Save Blocks</button> 
                            <button onclick="Code.restoreBlocks()" class="btn btn-default btn-xs">Undo All</button> 
                            <button onclick="Code.discardBlocks()" class="btn btn-default btn-xs">Clear</button> 
                            <input name="close" value="{{ _('Close','button') }}" type="submit" class="btn btn-default btn-xs">
                              </form>
                                  </td>
                                </tr>
                              </table>
                            </td>
                          </tr>
                          <tr>
                            <td height="99%" colspan=1 id="content_area">
                            </td>
                          </tr>
                        </table>
                        <div id="content_blocks" class="content"></div>
                        <pre id="content_python" class="content"></pre>
                        <textarea id="content_xml" class="content" wrap="off"></textarea>
                      
                      <script>
                      /**
                       * Create a namespace for the application.
                       */
                      var Code = {};
                            
                      /**
                       * Blockly's main workspace.
                       * @type {Blockly.WorkspaceSvg}
                       */
                      Code.workspace = null;
                      
                      /**
                       * Restore code blocks from localStorage.
                       * @param {Blockly.WorkspaceSvg=} opt_workspace Workspace.
                       */
                      Code.restoreBlocks = function() {
                        var request = $.ajax({'url': '/logics_blockly_load', dataType: 'text'});
                        request.done(function(response) 
                        {
                          var xml = Blockly.Xml.textToDom(response);
                          //var xml = response;
                          //alert('Request success: ' + response);
                          var workspace = Blockly.getMainWorkspace();
                          Blockly.Xml.domToWorkspace(xml, workspace);
                        });
                        request.fail(function(jqXHR, textStatus) 
                        {
                          alert('Request failed: ' + textStatus);
                        });
                        Code.renderContent()
                      };
                      
                      /**
                       * Load blocks saved on App Engine Storage or in session/local storage.
                       * @param {string} defaultXml Text representation of default blocks.
                       */
                      Code.loadBlocks = function(defaultXml) {
                       if (defaultXml) {
                         // Load the editor with default starting blocks.
                         var xml = Blockly.Xml.textToDom(defaultXml);
                         Blockly.Xml.domToWorkspace(xml, Code.workspace);
                       } else {
                         // Restore saved blocks in a separate thread so that subsequent
                         // initialization is not affected from a failed load.
                         window.setTimeout(Code.restoreBlocks, 0);
                       }
                      };
                      
                      Code.saveBlocks = function() {
                        Code.workspace;
                        var xml = Blockly.Xml.workspaceToDom(Code.workspace);
                        var xmldata = Blockly.Xml.domToText(xml);
                        var pycode = Blockly.Python.workspaceToCode(Code.workspace);
                        $.ajax({  url: "/logics_blockly_save",
                                  type: "POST",
                                  data: {xml: xmldata, py: pycode },
                                  //success: function(response) {
                                  //    alert(response +' ?');
                                  //    $("#test").html(response);
                                  //} 
                              });
                      };
                      
                      
                      /**
                       * Discard all blocks from the workspace.
                       */
                      Code.discardBlocks = function() {
                        var count = Code.workspace.getAllBlocks().length;
                        if (count < 2 ||
                            window.confirm(Blockly.Msg.DELETE_ALL_BLOCKS.replace('%1', count))) {
                          Code.workspace.clear();
                          Code.renderContent();
                        }
                      };
                      
                      
                      /**
                       * Bind a function to a button's click event.
                       * On touch enabled browsers, ontouchend is treated as equivalent to onclick.
                       * @param {!Element|string} el Button element or ID thereof.
                       * @param {!Function} func Event handler to bind.
                       */
                      Code.bindClick = function(el, func) {
                        if (typeof el == 'string') {
                          el = document.getElementById(el);
                        }
                        el.addEventListener('click', func, true);
                        el.addEventListener('touchend', func, true);
                      };
                      
                      
                      /**
                       * List of tab names.
                       * @private
                       */
                      Code.TABS_ = ['blocks', 'python', 'xml'];
                      
                      Code.selected = 'blocks';
                      
                      /**
                       * Switch the visible pane when a tab is clicked.
                       * @param {string} clickedName Name of tab clicked.
                       */
                      Code.tabClick = function(clickedName) {
                        // If the XML tab was open, save and render the content.
                        if (document.getElementById('tab_xml').className == 'tabon') {
                          var xmlTextarea = document.getElementById('content_xml');
                          var xmlText = xmlTextarea.value;
                          var xmlDom = null;
                          try {
                            xmlDom = Blockly.Xml.textToDom(xmlText);
                          } catch (e) {
                            var q =
                                window.confirm(MSG['badXml'].replace('%1', e));
                            if (!q) {
                              // Leave the user on the XML tab.
                              return;
                            }
                          }
                          if (xmlDom) {
                            Code.workspace.clear();
                            Blockly.Xml.domToWorkspace(xmlDom, Code.workspace);
                          }
                        }
                      
                        if (document.getElementById('tab_blocks').className == 'tabon') {
                          Code.workspace.setVisible(false);
                        }
                        // Deselect all tabs and hide all panes.
                        for (var i = 0; i < Code.TABS_.length; i++) {
                          var name = Code.TABS_[i];
                          document.getElementById('tab_' + name).className = 'taboff';
                          document.getElementById('content_' + name).style.visibility = 'hidden';
                        }
                      
                        // Select the active tab.
                        Code.selected = clickedName;
                        document.getElementById('tab_' + clickedName).className = 'tabon';
                        // Show the selected pane.
                        document.getElementById('content_' + clickedName).style.visibility =
                            'visible';
                        Code.renderContent();
                        if (clickedName == 'blocks') {
                          Code.workspace.setVisible(true);
                        }
                        Blockly.svgResize(Code.workspace);
                      };
                      
                      /**
                       * Populate the currently selected pane with content generated from the blocks.
                       */
                      Code.renderContent = function() {
                        var content = document.getElementById('content_' + Code.selected);
                        // Initialize the pane.
                        if (content.id == 'content_xml') {
                          var xmlTextarea = document.getElementById('content_xml');
                          var xmlDom = Blockly.Xml.workspaceToDom(Code.workspace);
                          var xmlText = Blockly.Xml.domToPrettyText(xmlDom);
                          xmlTextarea.value = xmlText;
                          xmlTextarea.focus();
                        } else if (content.id == 'content_python') {
                          code = Blockly.Python.workspaceToCode(Code.workspace);
                          content.textContent = code;
                          if (typeof prettyPrintOne == 'function') {
                            code = content.innerHTML;
                            code = prettyPrintOne(code, 'py');
                            content.innerHTML = code;
                          }
                        }
                      };
                      
                      
                      /**
                       * Compute the absolute coordinates and dimensions of an HTML element.
                       * @param {!Element} element Element to match.
                       * @return {!Object} Contains height, width, x, and y properties.
                       * @private
                       */
                      Code.getBBox_ = function(element) {
                        var height = element.offsetHeight;
                        var width = element.offsetWidth;
                        var x = 0;
                        var y = 0;
                        do {
                          x += element.offsetLeft;
                          y += element.offsetTop;
                          element = element.offsetParent;
                        } while (element);
                        return {
                          height: height,
                          width: width,
                          x: x,
                          y: y
                        };
                      };
                      
                      
                      /**
                       * Initialize Blockly.  Called on page load.
                       */
                      Code.init = function() {
                        //Code.initLanguage();
                      
                        //var rtl = Code.isRtl();
                        var container = document.getElementById('content_area');
                        var onresize = function(e) {
                          var bBox = Code.getBBox_(container);
                          for (var i = 0; i < Code.TABS_.length; i++) {
                            var el = document.getElementById('content_' + Code.TABS_[i]);
                            el.style.top = bBox.y + 'px';
                            el.style.left = bBox.x + 'px';
                            // Height and width need to be set, read back, then set again to
                            // compensate for scrollbars.
                            el.style.height = bBox.height + 'px';
                            el.style.height = (2 * bBox.height - el.offsetHeight) + 'px';
                            el.style.width = bBox.width + 'px';
                            el.style.width = (2 * bBox.width - el.offsetWidth) + 'px';
                          }
                          // Make the 'Blocks' tab line up with the toolbox.
                          if (Code.workspace && Code.workspace.toolbox_.width) {
                            document.getElementById('tab_blocks').style.minWidth =
                                (Code.workspace.toolbox_.width ) + 'px';
                                // Account for the 19 pixel margin and on each side.
                          }
                        };
                        window.addEventListener('resize', onresize, false);
                      
                        // Interpolate translated messages into toolbox.
                        var toolboxText = document.getElementById('toolbox').outerHTML;
                        //toolboxText = toolboxText.replace(/{(\w+)}/g,
                        //    function(m, p1) {return MSG[p1]});
                        var toolboxXml = Blockly.Xml.textToDom(toolboxText);
                      
                        Code.workspace = Blockly.inject('content_blocks',
                            {grid:
                                {spacing: 25,
                                 length: 3,
                                 colour: '#ccc',
                                 snap: true},
                             media: '../static/blockly/media/',
                             //rtl: rtl,
                             toolbox: toolboxXml,
                             zoom:
                                 {controls: true,
                                  wheel: true}
                            });
                      
                        // Add to reserved word list: Local variables in execution environment (runJS)
                        // and the infinite loop detection function.
                        //Blockly.JavaScript.addReservedWords('code,timeouts,checkTimeout');
                      
                        Code.loadBlocks('');
                      
                        //if ('BlocklyStorage' in window) {
                        //  // Hook a save function onto unload.
                        //  BlocklyStorage.backupOnUnload(Code.workspace);
                        //}
                      
                        Code.tabClick(Code.selected);
                      
                        for (var i = 0; i < Code.TABS_.length; i++) {
                          var name = Code.TABS_[i];
                          Code.bindClick('tab_' + name,
                              function(name_) {return function() {Code.tabClick(name_);};}(name));
                        }
                        onresize();
                        Blockly.svgResize(Code.workspace);
                      
                        // Lazy-load the syntax-highlighting.
                        window.setTimeout(Code.importPrettify, 1);
                      };
                      
                      window.addEventListener('load', Code.init);
                      
                      </script>
                      
                      {% endblock %}

                      Code:
                      class BackendBlocklyLogics:
                          """
                          Google Blockly for Logics
                          """
                      
                          @cherrypy.expose
                          def logics_blockly_start(self):
                              from lib.logic import Logic
                      
                              self.logger.debug("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                              self.logger.info("Blockly Logics aktivieren...")
                              self.logger.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n")
                      
                              sh = self._sh
                              prio = 3
                              blockly_logics = {}
                      
                              fn_py = self._sh._logic_dir + "blockly_logics.py"        
                              with open(fn_py, 'r') as fpy:
                                   code = fpy.read()
                              #code = self._pycode
                              bytecode = compile(code, '<string>', 'exec')
                      
                              s=[]
                              for name in sh.scheduler:
                                  if name.startswith('blockly_runner'):
                                      logger.info('Blockly Logics: remove '+ name)
                                      s.append(name)
                              for name in s:
                                  sh.scheduler.remove(name)
                      
                              for line in code.splitlines():
                                  if line and line.startswith('#?#'):
                                      id, __, trigger = line[3:].partition(':')
                                      by, __, val = trigger.partition('=')
                                      self.logger.debug('Blockly Logics: {} => {} :: {}'.format(id, by, val))
                                      logic = Logic(sh, 'blockly_runner_' + id, {'bytecode' : bytecode,})
                                      by = by.strip()
                                      val = val.strip()
                                      if by == 'cycle':
                                          sh.scheduler.add('blockly_runner_' +id, logic, prio=prio, cron=None, cycle=val)
                                          self.logger.debug('Blockly Logics: cycles     => '+ val)
                                      elif by == 'crontab':
                                          sh.scheduler.add('blockly_runner_' +id, logic, prio=prio, cron=val, cycle=None)
                                          self.logger.debug('Blockly Logics: crontabs   => '+ val)
                                      elif by == 'watchitem':
                                          logic.watch_item = val
                                          item = sh.return_item(val)
                                          item.add_logic_trigger(logic)
                                          self.logger.debug('Blockly Logics: watchitems => '+ val)
                          
                      
                      
                          @cherrypy.expose
                          def logics_blockly_stop(self):
                      
                              self.logger.debug("\n\n~~~~~~~~~~~~~+++~~~~~~~~~~~~~~")
                              self.logger.info("Blockly Logics de-aktivieren...")
                              self.logger.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n")
                      
                              sh = self._sh
                              s=[]
                              for name in sh.scheduler:
                                  if name.startswith('blockly_runner'):
                                      self.logger.debug('Blockly Logics: remove '+ name)
                                      s.append(name)
                              for name in s:
                                  sh.scheduler.remove(name)
                      
                              # for i in sh.returnItems(): watchitem löschen!
                      
                      
                          #@cherrypy.expose
                          #def logics_blockly_stop(self):
                          #    pass
                      
                      
                          @cherrypy.expose
                          def logics_blockly_save(self, py, xml):
                              self._pycode = py
                              self._xmldata = xml
                      
                              fn_py = self._sh._logic_dir + "blockly_logics.py"
                              fn_xml = self._sh._logic_dir + "blockly_logics.xml"
                              
                              self.logger.debug("Backend: logics_html: SAVE PY blockly logic = {0}\n '{1}'".format(fn_py, py))
                              with open(fn_py, 'w') as fpy:
                                  fpy.write(py)
                      
                              self.logger.debug("Backend: logics_html: SAVE XML blockly logic = {0}\n '{1}'".format(fn_xml, xml))
                              with open(fn_xml, 'w') as fxml:
                                  fxml.write(xml)
                      
                          @cherrypy.expose
                          def logics_blockly_load(self):
                              fn_xml = self._sh._logic_dir + "blockly_logics.xml"
                              return serve_file(fn_xml, content_type='application/xml')
                      
                      
                          def _DynToolbox(self, sh):
                              xml = '  <category name="Trigger"> \n'
                              xml += '    <block type="sh_trigger_item"> \n'
                              xml += '        <field name="TRIG_ITEM"></field>\n'
                              xml += '        <field name="ITEMLIST"></field>\n'
                              xml += '    </block> \n'
                              xml += '    <block type="sh_trigger_cycle"></block> \n'
                              xml += '    <block type="sh_trigger_sun"></block> \n'
                              xml += '    <block type="sh_trigger_daily"></block> \n'
                              xml += '  </category>\n'
                              
                              xml += '  <category name="SmartHome Items">\n'
                              xml += '      <block type="sh_item_get"></block> \n'
                              xml += '      <block type="sh_item_set"></block> \n'
                              xml += '      <block type="sh_item_hasattr"></block> \n'
                              xml += '      <block type="sh_item_attr"></block> \n'
                              xml += self._build_item_block_tree(self._sh.return_items(), "Items")
                              xml += '  </category>\n'
                              
                              return xml
                              
                              
                          def _build_item_block_tree(self, nodes, name="Items"):
                              items_sorted = sorted(nodes, key=lambda k: str.lower(k['_path']), reverse=False)
                              if len(items_sorted) > 1 :
                                  parent_items_sorted = []
                                  last_parent_item = None
                                  for item in items_sorted:
                                      if last_parent_item is None or last_parent_item._path not in item._path:
                                          parent_items_sorted.append(item)
                                          last_parent_item = item
                                          
                                  xml = '<category name="{0} ({1})">\n'.format(name, len(parent_items_sorted))
                                  for item in parent_items_sorted:
                                      if item._type in ['bool', 'num', 'str']:
                                          xml += '<block type="sh_item_obj" name="{0}"><field name="N">{0}</field><field name="P">{1}</field><field name="T">{2}</field></block>\n'.format(item._name, item._path, item.type())
                                      xml += self._build_item_block_tree(item.return_children(), item._name)
                                  xml += '</category>\n'       
                                  return xml
                              elif len(items_sorted) > 0 :
                                  item = items_sorted[0]
                                  if item._type in ['bool', 'num', 'str']:
                                      return ' <block type="sh_item_obj" name="{0}"><field name="N">{0}</field><field name="P">{1}</field><field name="T">{2}</field></block>\n'.format(item._name, item._path, item.type())
                                  else:
                                      return '\n'
                              else:
                                  return ''
                                          
                          @cherrypy.expose
                          def logics_blockly_html(self, start=None, stop=None):
                              """
                              returns the smarthomeNG ...
                              """
                              self.find_visu_plugin()
                      
                              self.logger.debug("Backend: logics_blockly_html: start = '{0}', stop = '{1}'".format(start, stop))
                              if start is not None:
                                  self.logger.debug("Backend: logics_html: Start/Activate blockly logic = '{0}'".format('blockly_logic.xml'))
                              elif stop is not None:
                                  self.logger.debug("Backend: logics_html: Stop/DeActivate blockly logic = '{0}'".format('blockly_logic.xml'))
                              
                              tmpl = self.env.get_template('logics_blockly.html')
                              return tmpl.render(smarthome=self._sh, dyn_sh_toolbox=self._DynToolbox(self._sh), visu_plugin=(self.visu_plugin is not None))
                      Angehängte Dateien

                      Kommentar


                        #26
                        walldi machst Du einen PR gegen SmartHomeNG DEV? Kann man auch neue Logiken anlegen?

                        Wegen Archivierung: ich fände das alleine wegen möglicher Bugs in der Erzeugung der Logiken wichtig. Sonst ist halt alles weg.

                        Kommentar


                          #27
                          Top!
                          Traum in Tüten!

                          Kommentar


                            #28
                            Zitat von psilo Beitrag anzeigen
                            walldi machst Du einen PR gegen SmartHomeNG DEV? ...
                            Ich sage mal so: ich habe die Noten alle beisammen, jetzt muss ich sie nur noch in die richtige Reihenfolge bringen...

                            Gibt es Ideen, wie das Backend-Plugin erweitert werden soll / kann? (Möglichst lose gekoppelt?)


                            Kann man auch neue Logiken anlegen?
                            Die Idee hier ist: ich habe alle Blockly-Logiken in einem Panel / Workspace. Jeweils geklammert durch die "Trigger"-Blöcke. (cron, watchitem, init, ...) Neue kann man immer hinzufügen. Jetzt könnte man diese Blöcke noch erweitern um Name, aktiv/inaktiv, Kommentar, ("was weiß ich"...)
                            Jeder Trigger-Block wird dann einzeln im Scheduler oder beim Item angemeldet.

                            Wegen Archivierung: ich fände das alleine wegen möglicher Bugs in der Erzeugung der Logiken wichtig. Sonst ist halt alles weg.
                            Wahrscheinlich nicht: wenn im erzeugten Python-Code ein Syntax-Bug sein sollte, ist der User (aus der Zielgruppe) sowieso außen vor - der erzeugte Python-Code ist nicht immer besonders "intuitiv". Verloren geht dann aber nichts, außer man löscht bewusst - insbesondere werden die "normalen" Logiken nicht angefasst.

                            Kommentar


                              #29
                              Das Thema losere Kopplung für Erweiterungen des Backend Plugins habe ich noch auf dem Zettel, komme im Moment allerdings nicht dazu.
                              Viele Grüße
                              Martin

                              There is no cloud. It's only someone else's computer.

                              Kommentar


                                #30
                                Gibts schon neue Initiativen bzgl. Backend-Integration?

                                Kommentar

                                Lädt...
                                X