Hallo,
ich habe jetzt mal versucht, den LBS für meinen einfachen Deltasol BS/2 so gut ich konnte anzupassen . Leider komme ich nicht mehr weiter und bräuchte bitte mal Eure Hilfe. Ich bekomme die Temperaturen richtig angezeigt (3 und 4 hab ich mit einem 1.2k Widerstand simuliert) und die Drehzahl in %, dann sind die Werte für die Betriebsstunden verschoben bzw. das Byte in dem der Handbetrieb zu sehen ist findet sich gar nicht.
Was mich noch verwirrt, der Regler hat eigentlich nur ein Relais...
Danke schon mal an Euch...
Gruß, Jan
Daten aus dem ResolServiceCenter
Tool.jpg
edomi.jpg
github.jpg
resol.jpg
ich habe jetzt mal versucht, den LBS für meinen einfachen Deltasol BS/2 so gut ich konnte anzupassen . Leider komme ich nicht mehr weiter und bräuchte bitte mal Eure Hilfe. Ich bekomme die Temperaturen richtig angezeigt (3 und 4 hab ich mit einem 1.2k Widerstand simuliert) und die Drehzahl in %, dann sind die Werte für die Betriebsstunden verschoben bzw. das Byte in dem der Handbetrieb zu sehen ist findet sich gar nicht.
Was mich noch verwirrt, der Regler hat eigentlich nur ein Relais...
Danke schon mal an Euch...
Gruß, Jan
Daten aus dem ResolServiceCenter
Tool.jpg
edomi.jpg
github.jpg
resol.jpg
PHP-Code:
###[DEF]###
[name = Resol DeltaSol BS/2 (VBus)]
[e#1 important = IP-Adresse ]
[e#2 important = Port #init=7053 ]
[e#3 important = Passwort #init=vbus ]
[e#5 option = Loglevel #init=3 ]
[a#1 = Temperatur Sensor 1 ]
[a#2 = Temperatur Sensor 2 ]
[a#3 = Temperatur Sensor 3 ]
[a#4 = Temperatur Sensor 4 ]
[a#5 = Drehzahl Relais 1 ]
[a#6 = Drehzahl Relais 2 ]
[a#7 = Fehlermaske ]
[a#8 = Handbetrieb ]
[a#9 = Betriebsstunden Relais 1 ]
[a#10 = Betriebsstunden Relais 2 ]
[a#11 = Wärmemenge ]
[a#12 = Status ]
[a#13 = Programm ]
[a#14 = Version ]
[v#1 = 0] // Exec gestartet
[v#2 = 0] // Zeitpunkt der letzten Daten
[v#3 = 0] // Send by Change Array
###[/DEF]###
###[HELP]###
Resol VBus-Decoder für Resol DeltaSol BS
Dieser LBS basiert nahezu vollständig auf dem <a href='https://knx-user-forum.de/forum/projektforen/edomi/1125369-lbs-resol-vbus-viessmann-vitosol-200#post1125369' target='_blank'>Resol VBus LBS</a> von Michael Schöberl (schobi) mit angepassten Ausgängen
und Dekodierung.
Nur getestet mit der Resol VBus/LAN-Schnittstelle.
Die Bennenung der Ausgänge entspricht dem <a href='http://www.resol.de/index/software/' target='_blank'>Resol Service Center Tool</a>
Hinweis: Andere Regler die auf dem VBus-Protokoll basieren haben andere Parameter.
Changelog:
0.1:
-initiale Version
0.2:
- Send by Change integriert
0.3:
- Fehler bei negativen Temperaturwerten korrigiert
###[/HELP]###
###[LBS]###
<?
function LB_LBSID($id) {
if ($E=logic_getInputs($id)) {
$V = explode('|', logic_getVar($id,3));
// Initalisierung der Variablen, wenn nicht vorhanden
for ($i=1;$i<=35;$i++) {
if (!isset($V[$i])) $V[$i] = -999;
}
logic_setVar($id,3,implode('|',$V));
// EXEC-Script starten
if (logic_getVar($id,1) == 0) {
logic_setVar($id,1,1);
LB_LBSID_debug($id," function LB_LBSID starting EXEC",7);
logic_callExec(LBSID,$id);
}
}
}
function LB_LBSID_debug($id, $s, $l) {
$E=logic_getInputs($id);
$DEBUG=$E[5]['value'];
$l<=$DEBUG && writeToCustomLog("DeltaSol SLL (LBSLBSID)",$l,"(ID$id): ".$s);
}
?>
###[/LBS]###
###[EXEC]###
<?
require(dirname(__FILE__)."/../../../../main/include/php/incl_lbsexec.php");
//bei Bedarf kann hier die maximale Ausführungszeit des Scripts angepasst werden (Default: 30 Sekunden)
//Beispiele:
set_time_limit(0); //Script soll unendlich laufen (kein Timeout)
//set_time_limit(60); //Script soll maximal 60 Sekunden laufen
sql_connect();
// turn off the errors
$error_handler = set_error_handler("myErrorHandler");
error_reporting(0);
// Globale Konstanten
define("STATE_WAIT_FOR_SYNC_BYTE_AA", 1);
define("STATE_DEST_BYTE_L", 2);
define("STATE_DEST_BYTE_H", 3);
define("STATE_SOURCE_BYTE_L", 4);
define("STATE_SOURCE_BYTE_H", 5);
define("STATE_PROTOCOL", 6);
define("STATE_COMMAND_BYTE_L", 7);
define("STATE_COMMAND_BYTE_H", 8);
define("STATE_NUM_FRAMES", 9);
define("STATE_HEADER_CHECKSUM", 10);
define("STATE_RECEIVE_DATA_FRAMES", 11);
define("STATE_DATA_CHECKSUM", 12);
//define("STATE_PROTOCOL", 13);
//define("STATE_PROTOCOL", 14);
if ($E=logic_getInputs($id)) {
debug($id,"Baustein startet ",7);
$connection = new stdClass;
if(!empty($E[1]['value'])){
$ipadresse=$E[1]['value'];
} else {
debug($id, "Keine IP Adresse angegeben, Abbruch",2);
finish();
exit();
}
if(!empty($E[2]['value'])){
$port=$E[2]['value'];
} else {
debug($id, "Keinen Port angegeben, Abbruch",2);
finish();
exit();
}
if(!empty($E[3]['value'])){
$pass=$E[3]['value'];
} else {
debug($id, "Kein Passwort angegeben setze auf vbus",2);
$pass = 'vbus';
}
while (getSysInfo(1)>=1) { //Hauptschleife (wird beim Beenden oder Neustart von EDOMI verlassen)
//Wichtig: getSysInfo(1) sorgt zudem dafür, dass die Datenbank-Verbindung aufrechterhalten wird!
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$connection->target = $socket;
if ($socket === false) {
debug($id, "socket_create() fehlgeschlagen: Grund: " . socket_strerror(socket_last_error()) . ", Abbruch",4);
if (is_object($socket))
socket_shutdown($connection->target, 2);
break;
} else {
debug($id,"socket_create() OK.",7);
}
debug($id, "Versuche mit IP '".$ipadresse."' auf Port '".$port."' zu verbinden ...",6);
$result = socket_connect($socket, $ipadresse, $port);
if ($result === false) {
debug($id,"socket_connect() fehlgeschlagen. Grund: ($result) " . socket_strerror(socket_last_error($socket)) . ", Abbruch",4);
if (is_object($socket))
socket_shutdown($connection->target, 2);
break;
} else {
debug($id,"socket_connect() OK",4);
}
read_from_bus($id, $connection, $pass);
// connection has problems, maybe try again with some waiting?
usleep(10*1000*1000);
if (is_object($connection->target)) {
debug($id,"closing sockets", 5);
socket_shutdown($connection->target, 2);
}
}
debug($id,"EXEC des Bausteins wird beendet", 4);
finish();
exit();
}
function finish() {
logic_setVar($id,1,0);
logic_setState($id,1,300,true);
// turn errors back on
restore_error_handler();
error_reporting(E_ALL);
sql_disconnect();
}
function read_from_bus($id, $connection, $pass) {
$e_nonblocking = 11; // Error code for EAGAIN or EWOULDBLOCK
if (!is_object($connection)) {
debug($id, "Fehler in read_from_bus() Parameter, Abbruch", 3);
finish();
}
$decoderstate = new StdClass();
$decoderstate->state = STATE_WAIT_FOR_SYNC_BYTE_AA;
$decoderstate->destaddr = "";
$decoderstate->sourceaddr = "";
while (getSysInfo(1)>=1) {
$sin = "";
$reciv = "";
if (false === ($bytes = socket_recv($connection->target, $sin, 45, MSG_DONTWAIT))) {
// no data, just wait and try again
usleep(100*1000);
} elseif (0 === $bytes) {
// some error has happened
if (socket_last_error() == $e_nonblocking) {
// non blocking socket has not returned anything, try again later
usleep(100*1000);
continue;
}
else {
debug($id, "socket_recv() failed; reason: ".socket_last_error()." " . socket_strerror(socket_last_error($connection->target)), 3);
debug($id, "connection seems broken/closed/aborted", 4);
usleep(1000*1000);
return 0;
}
} else {
$reciv = strtoupper((array_shift((unpack('H*', $sin)))));
debug($id, "read $bytes bytes from bus, data: " . $reciv, 7);
// Netzwerkverbindung initialisieren
if ($reciv == '2B48454C4C4F0A') { // +HELLO[LF]
$data = 'PASS '.$pass."\n";
socket_write($connection->target, $data, strlen($data));
debug($id, "password send: " . $data, 7);
} elseif ($reciv == '2B4F4B3A2050617373776F72642061636365707465640A') { // +OK: Password accepted[LF]
$data = "DATA\n";
socket_write($connection->target, $data, strlen($data));
debug($id, "password OK, request data: " . $data, 7);
} elseif ($reciv == '2B4F4B3A204461746120696E636F6D696E672E2E2E0A') { // +OK: Data incoming...[LF]
debug($id, "OK, data incoming...", 4);
} elseif ($reciv == '2D4552524F523A2050617373776F72642072656A656374656 40A') { // -ERROR: Password rejected[LF]
debug($id, "password error", 4);
} else {
$inbytearray = unpack("C*", $sin);
while (count($inbytearray) > 0) {
// process each byte seperately
$currentbyte = array_shift($inbytearray);
state_machine_parse_data($id, $currentbyte, $decoderstate);
}
usleep(10*1000);
}
}
}
return 0;
}
function state_machine_parse_data($id, $currentbyte, & $decoderstate) {
$newstate = $decoderstate->state; // in case nothing changes
switch($decoderstate->state) {
case STATE_WAIT_FOR_SYNC_BYTE_AA:
if ($currentbyte == 0xAA) {
$newstate = STATE_DEST_BYTE_L;
$decoderstate->crc = 0x7F; // reset crc
debug($id, "statemachine - Syncbyte:" . $newstate, 7);
}
break;
case STATE_DEST_BYTE_L:
$decoderstate->destaddr = $currentbyte;
update_crc($decoderstate, $currentbyte);
$newstate = STATE_DEST_BYTE_H;
break;
case STATE_DEST_BYTE_H:
$decoderstate->destaddr += $currentbyte<<8;
update_crc($decoderstate, $currentbyte);
$newstate = STATE_SOURCE_BYTE_L;
break;
case STATE_SOURCE_BYTE_L:
$decoderstate->sourceaddr = $currentbyte;
update_crc($decoderstate, $currentbyte);
$newstate = STATE_SOURCE_BYTE_H;
break;
case STATE_SOURCE_BYTE_H:
$decoderstate->sourceaddr += $currentbyte<<8;
update_crc($decoderstate, $currentbyte);
$newstate = STATE_PROTOCOL;
break;
case STATE_PROTOCOL:
if ($currentbyte == 0x10) { // Protocol version 1.0
$newstate = STATE_COMMAND_BYTE_L;
update_crc($decoderstate, $currentbyte);
}
else { // protocol version not supported, wait for next sync
$newstate = STATE_WAIT_FOR_SYNC_BYTE_AA;
}
break;
case STATE_COMMAND_BYTE_L:
$decoderstate->command = $currentbyte;
update_crc($decoderstate, $currentbyte);
$newstate = STATE_COMMAND_BYTE_H;
break;
case STATE_COMMAND_BYTE_H:
$decoderstate->command += $currentbyte<<8;
if ($decoderstate->command = 0x0100) { // "Paket enthält Daten für Slave"
$newstate = STATE_NUM_FRAMES;
update_crc($decoderstate, $currentbyte);
}
else { // command not supported, wait for next sync
$newstate = STATE_WAIT_FOR_SYNC_BYTE_AA;
}
break;
case STATE_NUM_FRAMES:
$decoderstate->num_frames_expected = $currentbyte;
update_crc($decoderstate, $currentbyte);
debug($id, "expecting ". $decoderstate->num_frames_expected ." frames destination 0x". dechex($decoderstate->destaddr) ." and source 0x". dechex($decoderstate->sourceaddr), 6);
$newstate = STATE_HEADER_CHECKSUM;
break;
case STATE_HEADER_CHECKSUM:
if ($decoderstate->crc == $currentbyte) { // crc ok
$newstate = STATE_RECEIVE_DATA_FRAMES;
$decoderstate->crc = 0x7F; // reset crc
$decoderstate->num_frames_received = 0;
$decoderstate->received_bytes = array();
}
else {
debug($id, "crc error, received 0x". dechex($currentbyte) ." but expected 0x". dechex($decoderstate->crc) .", skipping frame", 4);
$newstate = STATE_WAIT_FOR_SYNC_BYTE_AA;
}
break;
case STATE_RECEIVE_DATA_FRAMES;
if ($currentbyte == 0xAA) { // this should not happen!
$newstate = STATE_WAIT_FOR_SYNC_BYTE_AA;
debug($id, "unexpected AA in datastream - skipping ", 4);
}
else {
update_crc($decoderstate, $currentbyte);
if (count($decoderstate->received_bytes) >= 4) { // process septett
if ($currentbyte & 0x01) $decoderstate->received_bytes[0] += 128;
if ($currentbyte & 0x02) $decoderstate->received_bytes[1] += 128;
if ($currentbyte & 0x04) $decoderstate->received_bytes[2] += 128;
if ($currentbyte & 0x08) $decoderstate->received_bytes[3] += 128;
$decoderstate->num_frames_received += 1;
$newstate = STATE_DATA_CHECKSUM;
}
else {
array_push($decoderstate->received_bytes, $currentbyte);
}
}
break;
case STATE_DATA_CHECKSUM:
debug($id, count($decoderstate->received_bytes) ." bytes collected ", 8);
if ($decoderstate->crc == $currentbyte) { // crc ok
debug($id, "crc ok, received ". count($decoderstate->received_bytes) ." bytes", 8);
// do something with the data
process_data($id, $decoderstate->destaddr, $decoderstate->sourceaddr, $decoderstate->num_frames_received, $decoderstate->received_bytes);
if ($decoderstate->num_frames_received < $decoderstate->num_frames_expected) {
// prepare for receiving next frame
$newstate = STATE_RECEIVE_DATA_FRAMES;
$decoderstate->crc = 0x7F; // reset crc
$decoderstate->received_bytes = array();
}
else {
$newstate = STATE_WAIT_FOR_SYNC_BYTE_AA;
}
}
else {
debug($id, "crc error, received 0x". dechex($currentbyte) ." but expected 0x". dechex($decoderstate->crc) .", skipping frame", 4);
$newstate = STATE_WAIT_FOR_SYNC_BYTE_AA;
}
break;
default:
$newstate = STATE_WAIT_FOR_SYNC_BYTE_AA;
break;
}
if ($newstate != $decoderstate->state)
debug($id, "was in state $decoderstate->state and went to $newstate", 7);
$decoderstate->state = $newstate;
return $newstate;
}
function process_data($id, $dest_addr, $source_addr, $num_frames_received, $received_bytes) {
debug($id, "received parameters: dest_addr $dest_addr, source_addr $source_addr, num_frames_received $num_frames_received", 7);
switch($dest_addr) {
case 0x0010: { // DFR
debug($id, "destination DFR detected", 7);
switch($source_addr) {
case 0x4278: { // Resol DeltaSol SLL und Stiebel Eltron SOM 7 E plus Regler
debug($id, "source Resol DeltaSol SLL Regler detected", 7);
logic_setVar($id,2,microtime(true));
$V = explode('|', logic_getVar($id,3));
switch($num_frames_received) {
case 1: {
$temp1 = $received_bytes[0] + $received_bytes[1] * 256;
$temp1 = ($temp1>=32768) ? ($temp1-65535)/10 : $temp1/10;
if (abs($temp1-$V[1]) >= 0.5) {
logic_setOutput($id, 1, $temp1);
$V[1] = $temp1;
}
debug($id, "Temperatur 1: $temp1 °C", 6);
$temp2 = $received_bytes[2] + $received_bytes[3] * 256;
$temp2 = ($temp2>=32768) ? ($temp2-65535)/10 : $temp2/10;
if (abs($temp2-$V[2]) >= 0.5) {
logic_setOutput($id, 2, $temp2);
$V[2] = $temp2;
}
debug($id, "Temperatur 2: $temp2 °C", 6);
break;
}
case 2: {
$temp3 = $received_bytes[0] + $received_bytes[1] * 256;
$temp3 = ($temp3>=32768) ? ($temp3-65535)/10 : $temp3/10;
if (abs($temp3-$V[3]) >= 0.5) {
logic_setOutput($id, 3, $temp3);
$V[3] = $temp3;
}
debug($id, "Temperatur 3: $temp3 °C", 6);
$temp4 = $received_bytes[2] + $received_bytes[3] * 256;
$temp4 = ($temp4>=32768) ? ($temp4-65535)/10 : $temp4/10;
if (abs($temp4-$V[4]) >= 0.5) {
logic_setOutput($id, 4, $temp4);
$V[4] = $temp4;
}
debug($id, "Temperatur 4: $temp4 °C", 6);
break;
}
case 3: {
if ($received_bytes[0] != $V[5]) logic_setOutput($id, 5, $received_bytes[0]);
debug($id, "Drehzahl Relais 1 ($V[5]): ".$received_bytes[0]." %", 6);
$V[5] = $received_bytes[0];
if ($received_bytes[1] != $V[6]) logic_setOutput($id, 6, $received_bytes[1]);
debug($id, "Drehzahl Relais 2 ($V[6]): ".$received_bytes[1]." %", 6);
$V[6] = $received_bytes[1];
break;
}
case 4: {
if ($received_bytes[0] != $V[7]) logic_setOutput($id, 7, $received_bytes[0]);
debug($id, "Fehlermaske ($V[7]): ".$received_bytes[0], 6);
$V[7] = $received_bytes[0];
if ($received_bytes[1] != $V[8]) logic_setOutput($id, 8, $received_bytes[1]);
debug($id, "Handbetrieb ($V[8]): ".$received_bytes[1], 6);
$V[8] = $received_bytes[1];
break;
}
case 5: {
$betrieb_r1 = $received_bytes[0] + $received_bytes[1] * 256;
if ($betrieb_r1 != $V[9]) logic_setOutput($id, 9, $betrieb_r1);
debug($id, "Betriebsstunden Relais 1: ($V[9]): ".$betrieb_r1." h", 6);
$V[9] = $betrieb_r1;
break;
}
case 6: {
$betrieb_r2 = $received_bytes[0] + $received_bytes[1] * 256;
if ($betrieb_r2 != $V[10])logic_setOutput($id, 10, $betrieb_r2);
debug($id, "Betriebsstunden Relais 2 ($V[10]): ".$betrieb_r2." h", 6);
$V[10] = $betrieb_r2;
break;
}
case 7: {
$waerme = $received_bytes[0] + $received_bytes[1] * 256 + $received_bytes[2] * 1000 + $received_bytes[3] * 256000+ $received_bytes[4] * 1000000 + $received_bytes[5] * 256000000 ;
debug($id, "Wärmemenge ($V[11]): ".$waerme." Wh", 6);
if (abs($waerme-$V[11]) >= 0.5) {
logic_setOutput($id, 11, $waerme);
$V[11] = $waerme;
}
break;
}
case 8: {
if ($received_bytes[0] != $V[12]) logic_setOutput($id, 12, $received_bytes[0]);
$V[12] = $received_bytes[0];
debug($id, "Status ($V[12]): ".$received_bytes[0], 6);
break;
}
case 9: {
if ($received_bytes[0] != $V[13]) logic_setOutput($id, 13, $received_bytes[0]);
$V[13] = $received_bytes[0];
debug($id, "Version ($V[13]): ".$received_bytes[0], 6);
break;
}
case 10: {
$sw = $received_bytes[0] * 0.01 + $received_bytes[1] * 2.56;
if ($sw != $V[14]) logic_setOutput($id, 14, $sw);
debug($id, "SW-Version ($V[14]): ".$sw, 6);
$V[14] = $sw;
break;
}
default: {
debug($id, "Error: I'm not expecting any more frames here! got this: " . $received_bytes[0] ." und ". $received_bytes[1] ." und ". $received_bytes[2] ." und ". $received_bytes[3], 3);
}
}
logic_setVar($id,3,implode('|',$V));
break;
}
default: {
debug($id, "source addr $source_addr not implemented", 4);
}
}
break;
}
default: {
debug($id, "destination addr $dest_addr not implemented", 7);
}
}
}
// Note: for init, use $decoderstate->crc = 0x7F; // reset the crc
function update_crc(& $decoderstate, $currentbyte) {
$decoderstate->crc = (256 + $decoderstate->crc - $currentbyte) & 0x7F;
}
function myErrorHandler($errno, $errstr, $errfile, $errline) {
// debug($id, "File: $errfile | Error: $errno | Line: $errline | $errstr ");
}
function debug($id,$s,$l) {
$E=logic_getInputs($id);
$DEBUG=$E[5]['value'];
$l<=$DEBUG && writeToCustomLog("DeltaSol SLL (LBSLBSID)", $l, "(ID$id) : ".$s);
}
sql_disconnect();
?>
###[/EXEC]###
Kommentar