Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. JR-Home

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    J
    • Profile
    • Following 0
    • Followers 0
    • Topics 0
    • Posts 1
    • Best 0
    • Groups 0

    JR-Home

    @JR-Home

    0
    Reputation
    7
    Profile views
    1
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    JR-Home Follow

    Latest posts made by JR-Home

    • RE: Neuer Adapter für UniPi Board - Websocket

      @TOBO Das Unipi 1.1 Board finde ich wirklich klasse. Schade dass es dafür noch keinen fertigen Adapter gibt. Preis Leistungs/Verhältnis einfach unschlagbar.
      Da ich noch nicht weiß wie man einen Adapter schreibt, habe ich dennoch ein Java Script erstellt, mit dem man über das EVOK Interface die Relais und Eingänge wie gewohnt ansprechen kann. Für jeden Ein/Ausgang wird dabei ein Objekt angelegt. Wer kann daraus einen Adapter basteln?

      console.log("Starte UniPi 1.1 EVOK Interface V1.0."); 
      
      const csUnipi = "http://localhost:9599/rest/";
      const csUnipiObjectPath ="javascript.0.UniPi."
      var aOneWireIDs = {};
      
      // Liste der erwarteten OneWire IDs mit dem dazugehörenden IOBroker Objekt. Diese können über
      // das Unipi Control Panal mit http://Raspi-IP:UnipiEvokPort ermittelt werden.
      // Diese Tabelle stellt sicher, dass unter der ID immer derselbe Sensor gefunden wird, und sich
      // die Reihenfolge und Zugriff auf einen spezifischen Sensor auch bei Ausfall eines anderen Sensors 
      // nicht ändert!
      aOneWireIDs["28FF6419D5853EB0"] = csUnipiObjectPath + "Input.OneWire1.";
      aOneWireIDs["xyz"] = csUnipiObjectPath + "Input.OneWire2.";
      
      // Das Objekt das den Relais Status representiert anlegen
      // true wenn bereits vorhanden überschreiben, false nur falls nicht vorhanden anlegen
      createState( csUnipiObjectPath + "Status", 0, false, {name: 'Unipi Status', type: 'string', unit: 'Info'});
      var i;
      for (i = 1; i <= 8; i++) {
          createState( csUnipiObjectPath + "Relay.R" + i, 0, false, {name: 'Unipi Rel ' + i, type: 'number', min: 0, max: 1, unit: ''});
      }
      for (i = 1; i <= 12; i++) {
          createState( csUnipiObjectPath + "Input.I" + String( i ).padStart(2, '0'), 0, false, {name: 'Unipi Inp ' + i, type: 'number', min: 0, max: 1, unit: ''});
      }
      
      createState( csUnipiObjectPath + "Input.AI1", 0, false, {name: 'Unipi AInp 1', unit: ''});
      createState( csUnipiObjectPath + "Input.AI2", 0, false, {name: 'Unipi AInp 2', unit: ''});
      
      function AddOneWireObject( sOneWireAddress, sIOBrokerObjectPath )
      {
      //    console.log( `Adding OneWire Object: ${sIOBrokerObjectPath} Device ID: ${sOneWireAddress}` );
          createState( sIOBrokerObjectPath + "value", 0, false, {name: 'Unipi One Wire value', unit: '°C'});
          createState( sIOBrokerObjectPath + "typ", "not connected", false, {name: 'Unipi One Wire sensor type', unit: ''});
          createState( sIOBrokerObjectPath + "address", sOneWireAddress, false, {name: 'Unipi One Wire adress', unit: ''});
      };
      
      // Und die Datenpunkte für die OneWire Sensoren anlegen
      for (var key in aOneWireIDs ) {
          // OneWireIDs.forEach( function(key, value) {
          AddOneWireObject( key, aOneWireIDs[key] );
      };
      
      var request = require( "request" );
      
      function ReadUnipiInputs()
      {
          // Status aller Komponenten auslesen
          request( csUnipi + "all", function (error, response, body) {
              if( error != null )
              {
                  console.error( "Error accessing Unipi Evok: " + error );
                  setState( csUnipiObjectPath + "Status", "Last Error: " + error, true ); 
              }
              else
              {
                  setState( csUnipiObjectPath + "Status", "Available", true ); 
                  var json = JSON.parse(body);
                  // console.log ( "JSON: " + JSON.stringify(json) );
                  json.forEach( oUnipi => {
                      if( oUnipi.dev == "input" ) // && obj.circuit == "4")
                      {
                          // ACK=True, da Wert von "Hardware" geändert
                          // String( oUnipi.circuit ).padStart(2, '0') liefert die Input Nummer mit einer führenden Null
                          setState( csUnipiObjectPath + "Input.I" + String( oUnipi.circuit ).padStart(2, '0'), oUnipi.value, true ); 
                          // console.log( "Input " + obj.circuit + ":" + obj.value )
                          // Object.entries(obj).forEach(([key, value]) => {
                          // console.log(`${key} ${value}`);
                          // });
                      }
                      if( oUnipi.dev == "ai" )
                      {
                          // Tatsächlicher Wert der Hardware gelesen, daher ACK=TRUE
                          setState( csUnipiObjectPath + "Input.AI" + oUnipi.circuit, oUnipi.value, true ); 
                          //console.log( "Analog Input " + obj.circuit + ":" + obj.value )
                      }
                      // Falls sich der Zustand der Relais geändert hat (z. B. andere Zugriffe direkt auf EVOK) 
                      // dann diesen auch übernehmen
                      // Auch falls Ack noch nicht gesetzt sein sollte, "Wertübernahme durch HW" bestätigen
                      if( oUnipi.dev == "relay")
                      {
                          var oRel = getState( csUnipiObjectPath + "Relay.R" + oUnipi.circuit );
                          // Den Wert übernehmen wir aber nur mit Verzögerung, um zu verhindern, dass wir der asynchronen 
                          // Bearbeitung der "On" Event Funktion dazwischenfunken.
                          if( ( Number( oRel.val ) != oUnipi.value || oRel.ack != true ) && Date.now() - oRel.lc > 2000 )
                          {
                              // console.log( "TimeDiff: " + ( Date.now() - oRel.lc ) );
                              // Tatsächlicher Wert der Hardware gelesen, daher ACK=TRUE
                              setState( csUnipiObjectPath + "Relay.R" + oUnipi.circuit, oUnipi.value, true );
                          }
                      }
                      // Typ ist gesetzt bei den 1 Wire devices
                      if( oUnipi.typ > "" )
                      {
                          // Die I/O Broker Objekt ID ermitteln
                          var sOneWireObject = aOneWireIDs[ oUnipi.address ];
                          if( sOneWireObject > "" )
                          {
                              setState( sOneWireObject + "value", oUnipi.value, true );
                              if( getState( sOneWireObject + "typ" ).val != oUnipi.typ )
                              {
                                  setState( sOneWireObject + "typ", oUnipi.typ, true );
                              }
                              // Wird schon beim anlegen des Objektes gesetzt...
                              // setState( OneWireObject + "address", oUnipi.address, true );
                          }
                          else
                          {
                              var iLength = Object.keys( aOneWireIDs ).length + 1;    // aOneWire.length funktioniert bei einem assoziativen Array nicht....
                              console.error( "Error unknown One Wire device found. Please add new Datapoint: " + oUnipi.address + ". Temporary added as ID: " + iLength );
                              aOneWireIDs[oUnipi.address] = csUnipiObjectPath + "Input.OneWire_temp" + iLength + ".";
                              AddOneWireObject( oUnipi.address, aOneWireIDs[oUnipi.address] );
                          }    
                      }
                  }); 
              }
          });
      }
      
      schedule("*/1 * * * * *", function () { // Abfrage alle 1 Sec
          ReadUnipiInputs(); 
      });
      
      function WriteOutput( obj )
      {
          var RelNum = obj.id.substring(obj.id.length - 1);
      //    console.log( "Rel " + RelNum + " ObjID: " + obj.id + " Val: " + Number( obj.state.val ) + " Ack: " + obj.state.ack );
          // Nur falls der Wert nicht bereits von der Hardware bestätigt wurde übernehmen.
          if( obj.state.ack == false )
          {
              // Mit Number() wird das Objekt auch bei true/false in eine Zahl umgewandelt.
              request.post( csUnipi + "relay/" + RelNum, {form:{ value:Number( obj.state.val ) }}, function (error, response, body){
                  if( error == null )
                  {
                      // Schreiben auf die HW war erfolgreich, damit mit Ack=true bestätigen.
                      setState( obj.id, Number( obj.state.val ), true );
                  }
                  else
                  {
                      console.error( "Error accessing Unipi Evok: " + error );
                  }
              });
          }
      }
      
      // Damit nicht der On-Event für jedes Relais einzeln gesetzt werden muss 8x mit
      // on({id: csUnipiObjectPath + "Relay.R1", change: 'ne'}, function (obj) {
      // eine RegExpr. anlegen. Zu beachten: im String den \\ verdoppeln!
      // \d beliebige Zahl
      var RelObjectPath = csUnipiObjectPath + "Relay.R\\d";
      on({id: new RegExp( RelObjectPath.replace(".", "\\.") ), change: 'ne'}, function (obj) {
          WriteOutput( obj );
      });
      

      MOD-Edit: Code in code-tags gesetzt!

      posted in Entwicklung
      J
      JR-Home
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo