UPGRADE IP 9 verfügbar!
Timberwolf VISU jetzt mit NEUEM Layout Editor
Freie Anordnung, Reihenfolge und Größe der Widgets - viele weitere Verbesserungen
Infos im Wiki: https://elabnet.atlassian.net/l/cp/06SeuHRJ

NEU! Insider & Leistungsmerkmale FÜR ALLE freigeschaltet
Damit kann nun jeder das Upgrade vornehmen und VISU & IFTTT testen. Alle Info hier: viewtopic.php?f=8&t=5074

[NEUHEIT] Edomi 2.x für Desktop-Versionen der Timberwolf Server

Alles rund um Edomi im Allgemeinen und den entsprechenden Docker-Container für den Timberwolf Server im Speziellen.
Forumsregeln
  • Denke bitte an aussagekräftige Titel und gebe dort auch die [Firmware] an. Wenn ETS oder CometVisu beteiligt sind, dann auch deren Version
  • Bitte mache vollständige Angaben zu Deinem Server, dessen ID und dem Online-Status in Deiner Signatur. Hilfreich ist oft auch die Beschreibung der angeschlossener Hardware sowie die verwendeten Protokolle
  • Beschreibe Dein Projekt und Dein Problem bitte vollständig. Achte bitte darauf, dass auf Screenshots die Statusleiste sichtbar ist
  • Bitte sei stets freundlich und wohlwollend, bleibe beim Thema und unterschreibe mit deinem Vornamen. Bitte lese alle Regeln, die Du hier findest: https://wiki.timberwolf.io/Forenregeln

tger977
Reactions:
Beiträge: 740
Registriert: So Aug 12, 2018 9:25 am
Hat sich bedankt: 205 Mal
Danksagung erhalten: 274 Mal

#71

Beitrag von tger977 »

@jockele
So würd ich es machen.
bei 2) würde ich den Container nur stoppen, das gibt die IP Adresse auch frei und Du kannst im Falle des Falles den alten funktionierenden Container auch sofort wieder starten (nachdem natürlich die IP wieder frei ist)
bei 3) würde ich die aktualisierte Anleitung viewtopic.php?f=73&t=1841&start=40#p19699 nehmen, der KB Eintrag ist leider nicht mehr ganz aktuell, ich kann ihn aber auch nicht ändern.
bei 4) hatte ich manchmal mit dem Import Probleme. Beim ersten Importversuch ging es immer, bei weiteren scheiterte der Import. Warum weiss ich nicht...

Allgemein: bei mir läuft leider wieder der alte EDOMI2.00 Container mit CentOS5.x weiter da noch zu viele nicht PHP7 kompatible LBS sich bei mir zeigten...
Zuletzt geändert von tger977 am Sa Jan 11, 2020 12:43 pm, insgesamt 2-mal geändert.
Gruß
Andi

TW2500 #440 (ex Timberwolf 2400 #111) mit PBM #124, Support VPN nur auf Anfrage, Reboot bitte nur nach Absprache
Benutzeravatar

Ersteller
starwarsfan
Reactions:
Beiträge: 1152
Registriert: Mi Okt 10, 2018 2:39 pm
Hat sich bedankt: 744 Mal
Danksagung erhalten: 923 Mal

#72

Beitrag von starwarsfan »

Hallo @jockele,

meine Empfehlung wäre, ein komplett neues System aufzusetzen. Damit hast Du die 100%ige Möglichkeit, auf die alte Instanz zurückzukehren. Da Deine momentane Instanz ja schon Edomi 2.0 ist, ist das kein Problem.

Also die alte Instanz stoppen (nicht löschen!) neue Volumes erstellen, neues Instanz mit diesen Volumes konfigurieren, starten und dann das Backup zurückspielen. Da Du MacVLAN verwendest, wird es auch keinen Port-Konflikt geben.

Wie @tger977 schon schrieb, könnte es höchstens sein, dass Du Community-LBS verwendest, welche für Edomi 2.0 noch nicht fit gemacht wurden. Allerdings habe ich an dieser Stelle keine Probleme bisher, somit wär's auf jeden Fall einen Versuch wert. :handgestures-thumbupright:
Kind regards,
Yves

- TWS 2500 ID:159 (VPN offen, Reboot nach Rücksprache) - PBM ID:401 - TWS 3500 ID:618 (VPN offen, Reboot nach Rücksprache) - ControlPro - ProxMox - Edomi (LXC / Docker) - ... -
Benutzeravatar

Ersteller
starwarsfan
Reactions:
Beiträge: 1152
Registriert: Mi Okt 10, 2018 2:39 pm
Hat sich bedankt: 744 Mal
Danksagung erhalten: 923 Mal

#73

Beitrag von starwarsfan »

Hallo miteinander,

vor ein paar Minuten habe ich neue Versionen der Images auf DockerHub gepushed. Das Setup der Mosquitto-Requirements ist nun gefixt, so dass Edomi ohne die Fehlermeldung hinsichtlich libmosquitto startet.

Weiterhin habe ich den Email-Versand mit Edomi-Bordmitteln getestet und das funktioniert ebenfalls wunderbar.

Ich wäre dankbar für die folgenden Tests, da ich das bei mir nicht im Einsatz habe:
  • Mosquitto
  • Mailer-LBS
  • Und was euch sonst noch so einfällt :lol:
PS: Wer selber Images baut, bitte auch das Baseimage und das Builderimage updaten! Die Sourcen liegen wie immer auf Github, hier und hier.
Kind regards,
Yves

- TWS 2500 ID:159 (VPN offen, Reboot nach Rücksprache) - PBM ID:401 - TWS 3500 ID:618 (VPN offen, Reboot nach Rücksprache) - ControlPro - ProxMox - Edomi (LXC / Docker) - ... -

jockele
Reactions:
Beiträge: 187
Registriert: Mo Aug 13, 2018 8:40 pm
Wohnort: Steisslingen
Hat sich bedankt: 27 Mal
Danksagung erhalten: 39 Mal

#74

Beitrag von jockele »

danke für den support, läuft alles wieder :handgestures-thumbupright:

Im log taucht zwar folgender Eintrag auf: "Datei: /usr/local/edomi/main/include/php/ModbusMaster.php | Fehlercode: 8192 | Zeile: 38 | Methods with the same name as their class will not be constructors in a future version of PHP; ModbusMaster has a deprecated constructor"

und ich habe keine Ahnung was das bedeutet , aber zumindest scheint der Fehler bis jetzt nichts zu beeinträchtigen
Zuletzt geändert von jockele am Mo Jan 13, 2020 8:54 pm, insgesamt 1-mal geändert.
Timberwolf Server 2500, ID:142 + PBM
VPN offen, Reboot nach Absprache
Benutzeravatar

Ersteller
starwarsfan
Reactions:
Beiträge: 1152
Registriert: Mi Okt 10, 2018 2:39 pm
Hat sich bedankt: 744 Mal
Danksagung erhalten: 923 Mal

#75

Beitrag von starwarsfan »

Nunja, das heisst, dass ModbusMaster.php irgendwann nicht mehr funktionieren wird, also mit einer zukünftigen PHP-Version. Ein ToDo für den Autor dieser Klasse.
Kind regards,
Yves

- TWS 2500 ID:159 (VPN offen, Reboot nach Rücksprache) - PBM ID:401 - TWS 3500 ID:618 (VPN offen, Reboot nach Rücksprache) - ControlPro - ProxMox - Edomi (LXC / Docker) - ... -

tger977
Reactions:
Beiträge: 740
Registriert: So Aug 12, 2018 9:25 am
Hat sich bedankt: 205 Mal
Danksagung erhalten: 274 Mal

#76

Beitrag von tger977 »

jockele hat geschrieben: Mo Jan 13, 2020 8:52 pm Im log taucht zwar folgender Eintrag auf: "Datei: /usr/local/edomi/main/include/php/ModbusMaster.php | Fehlercode: 8192 | Zeile: 38 | Methods with the same name as their class will not be constructors in a future version of PHP; ModbusMaster has a deprecated constructor"

und ich habe keine Ahnung was das bedeutet , aber zumindest scheint der Fehler bis jetzt nichts zu beeinträchtigen
Hast du meine Anleitung gelesen? Da steht die Antwort drin...
Gruß
Andi

TW2500 #440 (ex Timberwolf 2400 #111) mit PBM #124, Support VPN nur auf Anfrage, Reboot bitte nur nach Absprache

jockele
Reactions:
Beiträge: 187
Registriert: Mo Aug 13, 2018 8:40 pm
Wohnort: Steisslingen
Hat sich bedankt: 27 Mal
Danksagung erhalten: 39 Mal

#77

Beitrag von jockele »

sorry, so weit habe ich nicht gelesen, nachdem Edomi lief hab ich nicht mehr weitergelesen!

Danke für den Hinweis
Timberwolf Server 2500, ID:142 + PBM
VPN offen, Reboot nach Absprache

jockele
Reactions:
Beiträge: 187
Registriert: Mo Aug 13, 2018 8:40 pm
Wohnort: Steisslingen
Hat sich bedankt: 27 Mal
Danksagung erhalten: 39 Mal

#78

Beitrag von jockele »

bräuchte hier aber nochmal Eure Hilfe, meine Modusmaster.php kommt aus dem E3DC Baustein (19000096), anbei der Code:

Code: Alles auswählen

<?php
/**
 * Phpmodbus Copyright (c) 2004, 2012 Jan Krakora
 *  
 * This source file is subject to the "PhpModbus license" that is bundled
 * with this package in the file license.txt.
 *   
 *
 * @copyright  Copyright (c) 2004, 2012 Jan Krakora
 * @license PhpModbus license 
 * @category Phpmodbus
 * @tutorial Phpmodbus.pkg 
 * @package Phpmodbus 
 * @version $id$
 *  
 */

require_once dirname(__FILE__) . '/IecType.php';
require_once dirname(__FILE__) . '/PhpType.php'; 

/**
 * ModbusMaster
 *
 * This class deals with the MODBUS master
 *  
 * Implemented MODBUS master functions:
 *   - FC  1: read coils
 *   - FC  3: read multiple registers
 *   - FC 15: write multiple coils 
 *   - FC 16: write multiple registers
 *   - FC 23: read write registers
 *   
 * @author Jan Krakora
 * @copyright  Copyright (c) 2004, 2012 Jan Krakora
 * @package Phpmodbus  
 *
 */
class ModbusMaster {
  private $sock;
  public $host = "192.168.1.1";
  public $port = "502";  
  public $client = "";
  public $client_port = "502";
  public $status;
  public $timeout_sec = 5; // Timeout 5 sec
  public $endianness = 0; // Endianness codding (little endian == 0, big endian == 1) 
  public $socket_protocol = "UDP"; // Socket protocol (TCP, UDP)
  
  /**
   * ModbusMaster
   *
   * This is the constructor that defines {@link $host} IP address of the object. 
   *     
   * @param String $host An IP address of a Modbus TCP device. E.g. "192.168.1.1"
   * @param String $protocol Socket protocol (TCP, UDP)   
   */         
  function ModbusMaster($host, $protocol){
    $this->socket_protocol = $protocol;
    $this->host = $host;
  }

  /**
   * __toString
   *
   * Magic method
   */
  function  __toString() {
      return "<pre>" . $this->status . "</pre>";
  }

  /**
   * connect
   *
   * Connect the socket
   *
   * @return bool
   */
  private function connect(){
    // Create a protocol specific socket 
    if ($this->socket_protocol == "TCP"){ 
        // TCP socket
        $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);      
    } elseif ($this->socket_protocol == "UDP"){
        // UDP socket
        $this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    } else {
        throw new Exception("Unknown socket protocol, should be 'TCP' or 'UDP'");
    }
    // Bind the client socket to a specific local port
    if (strlen($this->client)>0){
        $result = socket_bind($this->sock, $this->client, $this->client_port);
        if ($result === false) {
            throw new Exception("socket_bind() failed.</br>Reason: ($result)".
                socket_strerror(socket_last_error($this->sock)));
        } else {
            $this->status .= "Bound\n";
        }
    }
    // Connect the socket
    $result = @socket_connect($this->sock, $this->host, $this->port);
    if ($result === false) {
        throw new Exception("socket_connect() failed.</br>Reason: ($result)".
            socket_strerror(socket_last_error($this->sock)));
    } else {
        $this->status .= "Connected\n";
        return true;        
    }    
  }

  /**
   * disconnect
   *
   * Disconnect the socket
   */
  private function disconnect(){    
    socket_close($this->sock);
    $this->status .= "Disconnected\n";
  }

  /**
   * send
   *
   * Send the packet via Modbus
   *
   * @param string $packet
   */
  private function send($packet){
    socket_write($this->sock, $packet, strlen($packet));  
    $this->status .= "Send\n";
  }

  /**
   * rec
   *
   * Receive data from the socket
   *
   * @return bool
   */
  private function rec(){
    socket_set_nonblock($this->sock);
    $readsocks[] = $this->sock;     
    $writesocks = NULL;
    $exceptsocks = NULL;
    $rec = "";
    $lastAccess = time();
    while (socket_select($readsocks, 
            $writesocks, 
            $exceptsocks,
            0, 
            300000) !== FALSE) {
            $this->status .= "Wait data ... \n";
        if (in_array($this->sock, $readsocks)) {
            while (@socket_recv($this->sock, $rec, 2000, 0)) {
                $this->status .= "Data received\n";
                return $rec;
            }
            $lastAccess = time();
        } else {             
            if (time()-$lastAccess >= $this->timeout_sec) {
                throw new Exception( "Watchdog time expired [ " .
                  $this->timeout_sec . " sec]!!! Connection to " . 
                  $this->host . " is not established.");
            }
        }
        $readsocks[] = $this->sock;
    }
  } 
  
  /**
   * responseCode
   *
   * Check the Modbus response code
   *
   * @param string $packet
   * @return bool
   */
  private function responseCode($packet){    
    if((ord($packet[7]) & 0x80) > 0) {
      // failure code
      $failure_code = ord($packet[8]);
      // failure code strings
      $failures = array(
        0x01 => "ILLEGAL FUNCTION",
        0x02 => "ILLEGAL DATA ADDRESS",
        0x03 => "ILLEGAL DATA VALUE",
        0x04 => "SLAVE DEVICE FAILURE",
        0x05 => "ACKNOWLEDGE",
        0x06 => "SLAVE DEVICE BUSY",
        0x08 => "MEMORY PARITY ERROR",
        0x0A => "GATEWAY PATH UNAVAILABLE",
        0x0B => "GATEWAY TARGET DEVICE FAILED TO RESPOND");
      // get failure string
      if(key_exists($failure_code, $failures)) {
        $failure_str = $failures[$failure_code];
      } else {
        $failure_str = "UNDEFINED FAILURE CODE";
      }
      // exception response
      throw new Exception("Modbus response error code: $failure_code ($failure_str)");
    } else {
      $this->status .= "Modbus response error code: NOERROR\n";
      return true;
    }    
  }
  
  /**
   * readCoils
   * 
   * Modbus function FC 1(0x01) - Read Coils
   * 
   * Reads {@link $quantity} of Coils (boolean) from reference 
   * {@link $reference} of a memory of a Modbus device given by 
   * {@link $unitId}.
   * 
   * @param type $unitId
   * @param type $reference
   * @param type $quantity 
   */
  function readCoils($unitId, $reference, $quantity){
    $this->status = "readCoils: START\n";
    // connect
    $this->connect();
    // send FC 1
    $packet = $this->readCoilsPacketBuilder($unitId, $reference, $quantity);
    $this->status .= $this->printPacket($packet);    
    $this->send($packet);
    // receive response
    $rpacket = $this->rec();
    $this->status .= $this->printPacket($rpacket);    
    // parse packet    
    $receivedData = $this->readCoilsParser($rpacket, $quantity);
    // disconnect
    $this->disconnect();
    $this->status .= "readCoils: DONE\n";
    // return
    return $receivedData;
  }
  
  /**
   * fc1
   * 
   * Alias to {@link readCoils} method
   * 
   * @param type $unitId
   * @param type $reference
   * @param type $quantity
   * @return type 
   */
  function fc1($unitId, $reference, $quantity){
    return $this->readCoils($unitId, $reference, $quantity);
  }
  
  /**
   * readCoilsPacketBuilder
   * 
   * FC1 packet builder - read coils
   * 
   * @param type $unitId
   * @param type $reference
   * @param type $quantity
   * @return type 
   */
  private function readCoilsPacketBuilder($unitId, $reference, $quantity){
    $dataLen = 0;
    // build data section
    $buffer1 = "";
    // build body
    $buffer2 = "";
    $buffer2 .= iecType::iecBYTE(1);              // FC 1 = 1(0x01)
    // build body - read section    
    $buffer2 .= iecType::iecINT($reference);      // refnumber = 12288      
    $buffer2 .= iecType::iecINT($quantity);       // quantity
    $dataLen += 5;
    // build header
    $buffer3 = '';
    $buffer3 .= iecType::iecINT(rand(0,65000));   // transaction ID
    $buffer3 .= iecType::iecINT(0);               // protocol ID
    $buffer3 .= iecType::iecINT($dataLen + 1);    // lenght
    $buffer3 .= iecType::iecBYTE($unitId);        //unit ID
    // return packet string
    return $buffer3. $buffer2. $buffer1;
  }
  
  /**
   * readCoilsParser
   * 
   * FC 1 response parser
   * 
   * @param type $packet
   * @param type $quantity
   * @return type 
   */
  private function readCoilsParser($packet, $quantity){    
    $data = array();
    // check Response code
    $this->responseCode($packet);
    // get data from stream
    for($i=0;$i<ord($packet[8]);$i++){
      $data[$i] = ord($packet[9+$i]);
    }    
    // get bool values to array
    $data_bolean_array = array();
    $di = 0;
    foreach($data as $value){
      for($i=0;$i<8;$i++){
        if($di == $quantity) continue;
        // get boolean value 
        $v = ($value >> $i) & 0x01;
        // build boolean array
        if($v == 0){
          $data_bolean_array[] = FALSE;
        } else {
          $data_bolean_array[] = TRUE;
        }
        $di++;
      }
    }
    return $data_bolean_array;
  }
  
  /**
   * readInputDiscretes
   * 
   * Modbus function FC 2(0x02) - Read Input Discretes
   * 
   * Reads {@link $quantity} of Inputs (boolean) from reference 
   * {@link $reference} of a memory of a Modbus device given by 
   * {@link $unitId}.
   * 
   * @param type $unitId
   * @param type $reference
   * @param type $quantity 
   */
  function readInputDiscretes($unitId, $reference, $quantity){
    $this->status = "readInputDiscretes: START\n";
    // connect
    $this->connect();
    // send FC 2
    $packet = $this->readInputDiscretesPacketBuilder($unitId, $reference, $quantity);
    $this->status .= $this->printPacket($packet);    
    $this->send($packet);
    // receive response
    $rpacket = $this->rec();
    $this->status .= $this->printPacket($rpacket);    
    // parse packet    
    $receivedData = $this->readInputDiscretesParser($rpacket, $quantity);
    // disconnect
    $this->disconnect();
    $this->status .= "readInputDiscretes: DONE\n";
    // return
    return $receivedData;
  }
  
  /**
   * fc2
   * 
   * Alias to {@link readInputDiscretes} method
   * 
   * @param type $unitId
   * @param type $reference
   * @param type $quantity
   * @return type 
   */
  function fc2($unitId, $reference, $quantity){
    return $this->readInputDiscretes($unitId, $reference, $quantity);
  }
  
  /**
   * readInputDiscretesPacketBuilder
   * 
   * FC2 packet builder - read coils
   * 
   * @param type $unitId
   * @param type $reference
   * @param type $quantity
   * @return type 
   */
  private function readInputDiscretesPacketBuilder($unitId, $reference, $quantity){
    $dataLen = 0;
    // build data section
    $buffer1 = "";
    // build body
    $buffer2 = "";
    $buffer2 .= iecType::iecBYTE(2);              // FC 2 = 2(0x02)
    // build body - read section    
    $buffer2 .= iecType::iecINT($reference);      // refnumber = 12288      
    $buffer2 .= iecType::iecINT($quantity);       // quantity
    $dataLen += 5;
    // build header
    $buffer3 = '';
    $buffer3 .= iecType::iecINT(rand(0,65000));   // transaction ID
    $buffer3 .= iecType::iecINT(0);               // protocol ID
    $buffer3 .= iecType::iecINT($dataLen + 1);    // lenght
    $buffer3 .= iecType::iecBYTE($unitId);        //unit ID
    // return packet string
    return $buffer3. $buffer2. $buffer1;
  }
  
  /**
   * readInputDiscretesParser
   * 
   * FC 2 response parser, alias to FC 1 parser i.e. readCoilsParser.
   * 
   * @param type $packet
   * @param type $quantity
   * @return type 
   */
  private function readInputDiscretesParser($packet, $quantity){
    return $this->readCoilsParser($packet, $quantity);
  }
  
  /**
   * readMultipleRegisters
   *
   * Modbus function FC 3(0x03) - Read Multiple Registers.
   * 
   * This function reads {@link $quantity} of Words (2 bytes) from reference 
   * {@link $referenceRead} of a memory of a Modbus device given by 
   * {@link $unitId}.
   *    
   *
   * @param int $unitId usually ID of Modbus device 
   * @param int $reference Reference in the device memory to read data (e.g. in device WAGO 750-841, memory MW0 starts at address 12288).
   * @param int $quantity Amounth of the data to be read from device.
   * @return false|Array Success flag or array of received data.
   */
  function readMultipleRegisters($unitId, $reference, $quantity){
    $this->status = "readMultipleRegisters: START\n";
    // connect
    $this->connect();
    // send FC 3    
    $packet = $this->readMultipleRegistersPacketBuilder($unitId, $reference, $quantity);
    $this->status .= $this->printPacket($packet);    
    $this->send($packet);
    // receive response
    $rpacket = $this->rec();
    $this->status .= $this->printPacket($rpacket);    
    // parse packet    
    $receivedData = $this->readMultipleRegistersParser($rpacket);
    // disconnect
    $this->disconnect();
    $this->status .= "readMultipleRegisters: DONE\n";
    // return
    return $receivedData;
  }
  
  /**
   * fc3
   *
   * Alias to {@link readMultipleRegisters} method.
   *
   * @param int $unitId
   * @param int $reference
   * @param int $quantity
   * @return false|Array
   */
  function fc3($unitId, $reference, $quantity){
    return $this->readMultipleRegisters($unitId, $reference, $quantity);
  }  
  
  /**
   * readMultipleRegistersPacketBuilder
   *
   * Packet FC 3 builder - read multiple registers
   *
   * @param int $unitId
   * @param int $reference
   * @param int $quantity
   * @return string
   */
  private function readMultipleRegistersPacketBuilder($unitId, $reference, $quantity){
    $dataLen = 0;
    // build data section
    $buffer1 = "";
    // build body
    $buffer2 = "";
    $buffer2 .= iecType::iecBYTE(3);             // FC 3 = 3(0x03)
    // build body - read section    
    $buffer2 .= iecType::iecINT($reference);  // refnumber = 12288      
    $buffer2 .= iecType::iecINT($quantity);       // quantity
    $dataLen += 5;
    // build header
    $buffer3 = '';
    $buffer3 .= iecType::iecINT(rand(0,65000));   // transaction ID
    $buffer3 .= iecType::iecINT(0);               // protocol ID
    $buffer3 .= iecType::iecINT($dataLen + 1);    // lenght
    $buffer3 .= iecType::iecBYTE($unitId);        //unit ID
    // return packet string
    return $buffer3. $buffer2. $buffer1;
  }
  
  /**
   * readMultipleRegistersParser
   *
   * FC 3 response parser
   *
   * @param string $packet
   * @return array
   */
  private function readMultipleRegistersParser($packet){    
    $data = array();
    // check Response code
    $this->responseCode($packet);
    // get data
    for($i=0;$i<ord($packet[8]);$i++){
      $data[$i] = ord($packet[9+$i]);
    }    
    return $data;
  }
  
  /**
   * writeMultipleCoils
   * 
   * Modbus function FC15(0x0F) - Write Multiple Coils
   *
   * This function writes {@link $data} array at {@link $reference} position of 
   * memory of a Modbus device given by {@link $unitId}. 
   * 
   * @param type $unitId
   * @param type $reference
   * @param type $data
   * @return type 
   */
  function writeMultipleCoils($unitId, $reference, $data){
    $this->status = "writeMultipleCoils: START\n";
    // connect
    $this->connect();
    // send FC16    
    $packet = $this->writeMultipleCoilsPacketBuilder($unitId, $reference, $data);
    $this->status .= $this->printPacket($packet);    
    $this->send($packet);
    // receive response
    $rpacket = $this->rec();
    $this->status .= $this->printPacket($rpacket);    
    // parse packet
    $this->writeMultipleCoilsParser($rpacket);
    // disconnect
    $this->disconnect();
    $this->status .= "writeMultipleCoils: DONE\n";
    return true;
  }
  
  /**
   * fc15
   *
   * Alias to {@link writeMultipleCoils} method
   *
   * @param int $unitId
   * @param int $reference
   * @param array $data
   * @return bool
   */
  function fc15($unitId, $reference, $data){    
    return $this->writeMultipleCoils($unitId, $reference, $data);
  }
  
  /**
   * writeMultipleCoilsPacketBuilder
   *
   * Packet builder FC15 - Write multiple coils
   *
   * @param int $unitId
   * @param int $reference
   * @param array $data
   * @return string
   */
  private function writeMultipleCoilsPacketBuilder($unitId, $reference, $data){
    $dataLen = 0;    
    // build bool stream to the WORD array
    $data_word_stream = array();
    $data_word = 0;
    $shift = 0;    
    for($i=0;$i<count($data);$i++) {
      if((($i % 8) == 0) && ($i > 0)) {
        $data_word_stream[] = $data_word;
        $shift = 0;
        $data_word = 0;
        $data_word |= (0x01 && $data[$i]) << $shift;
        $shift++;
      }
      else {
        $data_word |= (0x01 && $data[$i]) << $shift;
        $shift++;
      }
    }
    $data_word_stream[] = $data_word;
    // show binary stream to status string
    foreach($data_word_stream as $d){
        $this->status .= sprintf("byte=b%08b\n", $d);
    }    
    // build data section
    $buffer1 = "";
    foreach($data_word_stream as $key=>$dataitem) {
        $buffer1 .= iecType::iecBYTE($dataitem);   // register values x
        $dataLen += 1;
    }
    // build body
    $buffer2 = "";
    $buffer2 .= iecType::iecBYTE(15);             // FC 15 = 15(0x0f)
    $buffer2 .= iecType::iecINT($reference);      // refnumber = 12288      
    $buffer2 .= iecType::iecINT(count($data));      // bit count      
    $buffer2 .= iecType::iecBYTE((count($data)+7)/8);       // byte count
    $dataLen += 6;
    // build header
    $buffer3 = '';
    $buffer3 .= iecType::iecINT(rand(0,65000));   // transaction ID    
    $buffer3 .= iecType::iecINT(0);               // protocol ID    
    $buffer3 .= iecType::iecINT($dataLen + 1);    // lenght    
    $buffer3 .= iecType::iecBYTE($unitId);        // unit ID    
     
    // return packet string
    return $buffer3. $buffer2. $buffer1;
  }
  
  /**
   * writeMultipleCoilsParser
   *
   * FC15 response parser
   *
   * @param string $packet
   * @return bool
   */
  private function writeMultipleCoilsParser($packet){
    $this->responseCode($packet);
    return true;
  }
  
  /**
   * writeMultipleRegister
   *
   * Modbus function FC16(0x10) - Write Multiple Register.
   *
   * This function writes {@link $data} array at {@link $reference} position of 
   * memory of a Modbus device given by {@link $unitId}.
   *
   *
   * @param int $unitId usually ID of Modbus device 
   * @param int $reference Reference in the device memory (e.g. in device WAGO 750-841, memory MW0 starts at address 12288)
   * @param array $data Array of values to be written.
   * @param array $dataTypes Array of types of values to be written. The array should consists of string "INT", "DINT" and "REAL".    
   * @return bool Success flag
   */       
  function writeMultipleRegister($unitId, $reference, $data, $dataTypes){
    $this->status = "writeMultipleRegister: START\n";
    // connect
    $this->connect();
    // send FC16    
    $packet = $this->writeMultipleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes);
    $this->status .= $this->printPacket($packet);    
    $this->send($packet);
    // receive response
    $rpacket = $this->rec();
    $this->status .= $this->printPacket($rpacket);    
    // parse packet
    $this->writeMultipleRegisterParser($rpacket);
    // disconnect
    $this->disconnect();
    $this->status .= "writeMultipleRegister: DONE\n";
    return true;
  }


  /**
   * fc16
   *
   * Alias to {@link writeMultipleRegister} method
   *
   * @param int $unitId
   * @param int $reference
   * @param array $data
   * @param array $dataTypes
   * @return bool
   */
  function fc16($unitId, $reference, $data, $dataTypes){    
    return $this->writeMultipleRegister($unitId, $reference, $data, $dataTypes);
  }


  /**
   * writeMultipleRegisterPacketBuilder
   *
   * Packet builder FC16 - WRITE multiple register
   *     e.g.: 4dd90000000d0010300000030603e807d00bb8
   *
   * @param int $unitId
   * @param int $reference
   * @param array $data
   * @param array $dataTypes
   * @return string
   */
  private function writeMultipleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes){
    $dataLen = 0;
    // build data section
    $buffer1 = "";
    foreach($data as $key=>$dataitem) {
      if($dataTypes[$key]=="INT"){
        $buffer1 .= iecType::iecINT($dataitem);   // register values x
        $dataLen += 2;
      }
      elseif($dataTypes[$key]=="DINT"){
        $buffer1 .= iecType::iecDINT($dataitem, $this->endianness);   // register values x
        $dataLen += 4;
      }
      elseif($dataTypes[$key]=="REAL") {
        $buffer1 .= iecType::iecREAL($dataitem, $this->endianness);   // register values x
        $dataLen += 4;
      }       
      else{
        $buffer1 .= iecType::iecINT($dataitem);   // register values x
        $dataLen += 2;
      }
    }
    // build body
    $buffer2 = "";
    $buffer2 .= iecType::iecBYTE(16);             // FC 16 = 16(0x10)
    $buffer2 .= iecType::iecINT($reference);      // refnumber = 12288      
    $buffer2 .= iecType::iecINT($dataLen/2);        // word count      
    $buffer2 .= iecType::iecBYTE($dataLen);     // byte count
    $dataLen += 6;
    // build header
    $buffer3 = '';
    $buffer3 .= iecType::iecINT(rand(0,65000));   // transaction ID    
    $buffer3 .= iecType::iecINT(0);               // protocol ID    
    $buffer3 .= iecType::iecINT($dataLen + 1);    // lenght    
    $buffer3 .= iecType::iecBYTE($unitId);        //unit ID    
    
    // return packet string
    return $buffer3. $buffer2. $buffer1;
  }
  
  /**
   * writeMultipleRegisterParser
   *
   * FC16 response parser
   *
   * @param string $packet
   * @return bool
   */
  private function writeMultipleRegisterParser($packet){
    $this->responseCode($packet);
    return true;
  }
  
  /**
   * readWriteRegisters
   *
   * Modbus function FC23(0x17) - Read Write Registers.
   * 
   * This function writes {@link $data} array at reference {@link $referenceWrite} 
   * position of memory of a Modbus device given by {@link $unitId}. Simultanously, 
   * it returns {@link $quantity} of Words (2 bytes) from reference {@link $referenceRead}.
   *
   *
   * @param int $unitId usually ID of Modbus device 
   * @param int $referenceRead Reference in the device memory to read data (e.g. in device WAGO 750-841, memory MW0 starts at address 12288).
   * @param int $quantity Amounth of the data to be read from device.   
   * @param int $referenceWrite Reference in the device memory to write data.
   * @param array $data Array of values to be written.
   * @param array $dataTypes Array of types of values to be written. The array should consists of string "INT", "DINT" and "REAL".   
   * @return false|Array Success flag or array of data.
   */
  function readWriteRegisters($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){
    $this->status = "readWriteRegisters: START\n";
    // connect
    $this->connect();
    // send FC23    
    $packet = $this->readWriteRegistersPacketBuilder($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes);
    $this->status .= $this->printPacket($packet);    
    $this->send($packet);
    // receive response
    $rpacket = $this->rec();
    $this->status .= $this->printPacket($rpacket);
    // parse packet
    $receivedData = $this->readWriteRegistersParser($rpacket);
    // disconnect
    $this->disconnect();
    $this->status .= "writeMultipleRegister: DONE\n";
    // return
    return $receivedData;
  }
  
  /**
   * fc23
   *
   * Alias to {@link readWriteRegisters} method.
   *
   * @param int $unitId
   * @param int $referenceRead
   * @param int $quantity
   * @param int $referenceWrite
   * @param array $data
   * @param array $dataTypes
   * @return false|Array
   */
  function fc23($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){
    return $this->readWriteRegisters($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes);
  }
  
  /**
   * readWriteRegistersPacketBuilder
   *
   * Packet FC23 builder - READ WRITE registers
   *
   *
   * @param int $unitId
   * @param int $referenceRead
   * @param int $quantity
   * @param int $referenceWrite
   * @param array $data
   * @param array $dataTypes
   * @return string
   */
  private function readWriteRegistersPacketBuilder($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){
    $dataLen = 0;
    // build data section
    $buffer1 = "";
    foreach($data as $key => $dataitem) {
      if($dataTypes[$key]=="INT"){
        $buffer1 .= iecType::iecINT($dataitem);   // register values x
        $dataLen += 2;
      }
      elseif($dataTypes[$key]=="DINT"){
        $buffer1 .= iecType::iecDINT($dataitem, $this->endianness);   // register values x
        $dataLen += 4;
      }
      elseif($dataTypes[$key]=="REAL") {
        $buffer1 .= iecType::iecREAL($dataitem, $this->endianness);   // register values x
        $dataLen += 4;
      }       
      else{
        $buffer1 .= iecType::iecINT($dataitem);   // register values x
        $dataLen += 2;
      }
    }
    // build body
    $buffer2 = "";
    $buffer2 .= iecType::iecBYTE(23);             // FC 23 = 23(0x17)
    // build body - read section    
    $buffer2 .= iecType::iecINT($referenceRead);  // refnumber = 12288      
    $buffer2 .= iecType::iecINT($quantity);       // quantity
    // build body - write section    
    $buffer2 .= iecType::iecINT($referenceWrite); // refnumber = 12288      
    $buffer2 .= iecType::iecINT($dataLen/2);      // word count      
    $buffer2 .= iecType::iecBYTE($dataLen);       // byte count
    $dataLen += 10;
    // build header
    $buffer3 = '';
    $buffer3 .= iecType::iecINT(rand(0,65000));   // transaction ID    
    $buffer3 .= iecType::iecINT(0);               // protocol ID    
    $buffer3 .= iecType::iecINT($dataLen + 1);    // lenght    
    $buffer3 .= iecType::iecBYTE($unitId);        //unit ID    
    
    // return packet string
    return $buffer3. $buffer2. $buffer1;
  }
  

  /**
   * readWriteRegistersParser
   *
   * FC23 response parser
   *
   * @param string $packet
   * @return array
   */
  private function readWriteRegistersParser($packet){
    $data = array();
    // if not exception
    if(!$this->responseCode($packet))
      return false;
    // get data
    for($i=0;$i<ord($packet[8]);$i++){
      $data[$i] = ord($packet[9+$i]);
    }    
    return $data;
  }

  /**
   * byte2hex
   *
   * Parse data and get it to the Hex form
   *
   * @param char $value
   * @return string
   */
  private function byte2hex($value){
    $h = dechex(($value >> 4) & 0x0F);
    $l = dechex($value & 0x0F);
    return "$h$l";
  }

  /**
   * printPacket
   *
   * Print a packet in the hex form
   *
   * @param string $packet
   * @return string
   */
  private function printPacket($packet){
    $str = "";   
    $str .= "Packet: "; 
    for($i=0;$i<strlen($packet);$i++){
      $str .= $this->byte2hex(ord($packet[$i]));
    }
    $str .= "\n";
    return $str;
  }
}
So wie ich als kompletter PHP-Laie die Anleitung im PDF verstehe habe ich "function ModbusMaster($host, $protocol)" ersetzt durch "function __construct($host, $protocol)", allerdings wirft Edomi dann die folgende Fehlermeldung im log aus :"syntax error, unexpected 'function __construct' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)"

Kann mir jemand weiterhelfen???

Vielen Dank
Timberwolf Server 2500, ID:142 + PBM
VPN offen, Reboot nach Absprache

StefanW
Elaborated Networks
Reactions:
Beiträge: 9689
Registriert: So Aug 12, 2018 9:27 am
Wohnort: Frauenneuharting
Hat sich bedankt: 4831 Mal
Danksagung erhalten: 7633 Mal
Kontaktdaten:

#79

Beitrag von StefanW »

Hallo Jockele,

wäre das nicht etwas sinnvolles für einen extra Thread?

Weil hier geht es um Edomi 2.x auf TWS im allgemeinen, nicht um eine Edmi-Logikfunktion für eine Hausbatterie im besonderen. Eine Antwort darauf findet später niemand und dann ist anderen suchenden nicht geholfen.

==> Bitte einen separaten Thread hier im Edomi-Unterforum aufmachen.

lg

Stefan
Stefan Werner
Product Owner für Timberwolf Server, 1-Wire und BlitzART
Bitte WIKI lesen. Allg. Support nur im Forum. Bitte keine PN
Zu Preisen, Lizenzen, Garantie, HW-Defekt an service at elabnet dot de

Link zu Impressum und Datenschutzerklärung oben.

jockele
Reactions:
Beiträge: 187
Registriert: Mo Aug 13, 2018 8:40 pm
Wohnort: Steisslingen
Hat sich bedankt: 27 Mal
Danksagung erhalten: 39 Mal

#80

Beitrag von jockele »

Hallo,

ich habe den Thread verschoben viewtopic.php?f=73&t=1903, gerne kann ein Mod die Beiträge hier verschieben bzw. löschen,

Grüße Jockele
Timberwolf Server 2500, ID:142 + PBM
VPN offen, Reboot nach Absprache
Antworten

Zurück zu „Docker Container: Edomi“