#!/usr/bin/perl
use Proc::Daemon;
Proc::Daemon::Init;
Proc::Daemon::Init({ pid_file => "/tmp/DaliAllg.pid"} );

system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/GetDataFromSensor1.pid";
system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/DaliIdent.pid";


my $SPID=`grep ^PID /scripts/work/sonstiges/neustart | cut -d "=" -f 2 | tr -d "\n"`;
my $ClientID = ${ARGV[1]};
my $Sec = `date +%s`;
chomp($Sec);
my $DaliID = 100 + $ARGV[0];
my $Interface=`/ids/$SPID/scripts/work/sonstiges/DbAbfrageC TasterSchnittstelle`;
my @DaliAdressRange = (1..64);

my $DaliQuery = DaliQuery(1); 

my $DaliWrite = DaliWrite(2, 9); 

select(undef, undef, undef, 1);
AGAIN:
my $DaliQuery = DaliQuery(1);


if ($DaliQuery == 2){
select(undef, undef, undef, 1);
goto AGAIN;
}

if ($DaliQuery == 4){
system "/scripts/work/2dbs/GoPlGoS CLIENTFRONTUPDATE \"$Sec~$ClientID~DaliInfoStatusReg1;$ARGV[0];4\"";
system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/GetDataFromSensor1.pid";
system "/sbin/start-stop-daemon -S -x /usr/bin/nohup /scripts/work/sonstiges/GetDataFromSensor1  -m --pidfile /tmp/GetDataFromSensor1.pid >/dev/null 2>&1 &";
exit 0;
}


if ($DaliQuery == 3 or $DaliQuery == 1){

	foreach(@DaliAdressRange){
	$RegisterAdr = 3000 + $_;

	my $DaliValue = DaliQuery($RegisterAdr);


	print "DaliValue:$DaliValue in RegisterAdr:$RegisterAdr\n";

		if ($DaliValue ne "0"){
			my $DaliAdresse = 100 + $_;
			$NumberOfInstancesReg = 3100 + $_;
			$NumberOfGTIN1Reg = 3300 + $_;
			$NumberOfGTIN2Reg = 3400 + $_;
			$NumberOfGTIN3Reg = 3500 + $_;

			print("Check in NumberOfInstancesReg:$NumberOfInstancesReg\n");	
			my $NumberOfInstances = DaliQuery($NumberOfInstancesReg);
			print "NumberOfInstances:$NumberOfInstances bei DaliAdresse:$DaliAdresse\n";

			####GTIN search and calc
			my $reg3301 = DaliQuery($NumberOfGTIN1Reg);
			my $reg3401 = DaliQuery($NumberOfGTIN2Reg);
			my $reg3501 = DaliQuery($NumberOfGTIN3Reg);

			# Die 3 Register in der Reihenfolge 3301, 3401, 3501 in Bytes zerlegen
			my @words = ($reg3301, $reg3401, $reg3501);
			my @raw_bytes;
			for my $w (@words) {
    				push @raw_bytes, (($w >> 8) & 0xFF); # High Byte
    				push @raw_bytes, ($w & 0xFF);        # Low Byte
			}

			# Der XOR-Key (aus deinem Beispiel hergeleitet)
			my @key = (0xF2, 0xB9, 0xC1, 0xD3, 0x8E, 0x22);

			# Rohbytes mit dem Key XOR-en → ergibt BCD-Bytes
			my @bcd_bytes;
			for my $i (0..$#raw_bytes) {
    				push @bcd_bytes, $raw_bytes[$i] ^ $key[$i];
			}

			# BCD-Bytes in Dezimalziffern aufsplitten
			my $body12 = '';
			for my $b (@bcd_bytes) {
    				my $hi = ($b >> 4) & 0xF;
    				my $lo = $b & 0xF;
    				$body12 .= $hi . $lo;
			}

			# nur die ersten 12 Ziffern für den EAN-Body nehmen
			$body12 = substr($body12, 0, 12);

			# Prüfziffer für EAN-13 berechnen
			sub ean13_checkdigit {
    				my ($digits) = @_;
    				my @nums = split //, $digits;
    				my $sum = 0;
    				for my $i (0..$#nums) {
        				my $n = $nums[$#nums - $i]; # von rechts zählen
        				$sum += ($i % 2 ? 3 : 1) * $n;
    				}
    			return (10 - ($sum % 10)) % 10;
			}

			my $check = ean13_checkdigit($body12);
			my $gtin13 = $body12 . $check;

			print "GTIN-13: $gtin13\n";
			####



		$StringToSend = $StringToSend.">".$_."<".$NumberOfInstances."<".$gtin13."<".$DaliValue;
		}
		else {
		$StringToSend = $StringToSend.">".$_."<<<".$DaliValue;
		}

	}

$StringToSend =~ s/^.//;
system "/scripts/work/2dbs/GoPlGoS CLIENTFRONTUPDATE \"$Sec~$ClientID~Dali2InfoBack;DaliGwErreichbar;$ARGV[0];$StringToSend\"";

select(undef, undef, undef, 0.5);

#my $DaliWrite = `/scripts/work/sonstiges/ModbusAbfrageSend Send $DaliID $Interface 57600 2 6`;
#if ($DaliWrite eq "FF"){
#system "/scripts/work/2dbs/GoPlGoS CLIENTFRONTUPDATE \"$Sec~$ClientID~DaliInfoBack;DaliGwNichtErreichbar;$ARGV[0]\"";
#system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/GetDataFromSensor1.pid";
#system "/sbin/start-stop-daemon -S -x /usr/bin/nohup /scripts/work/sonstiges/GetDataFromSensor1  -m --pidfile /tmp/GetDataFromSensor1.pid >/dev/null 2>&1 &";
#exit 0;
#}

select(undef, undef, undef, 0.5);
system "/scripts/work/2dbs/GoPlGoS CLIENTFRONTUPDATE \"$Sec~$ClientID~Dali2InfoFinBack;$ARGV[0]\"";
system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/GetDataFromSensor1.pid";
system "/sbin/start-stop-daemon -S -x /usr/bin/nohup /scripts/work/sonstiges/GetDataFromSensor1  -m --pidfile /tmp/GetDataFromSensor1.pid >/dev/null 2>&1 &";

print("StringToSend:$StringToSend\n");

}






sub DaliQuery {
	my ($register) = @_;

	my $DaliStart = `/scripts/work/sonstiges/ModbusAbfrageSend Abfrage $DaliID $Interface 57600 $register - DEBUGOFF 2000000`;
	chomp($DaliStart);    # Leerzeichen/Zeilenende entfernen

	if ($DaliStart eq "FF") {
		print "ERROR:FF\n";
		system "/scripts/work/2dbs/GoPlGoS CLIENTFRONTUPDATE \"$Sec~$ClientID~DaliInfoBack;DaliGwNichtErreichbar;$ARGV[0]\"";
		system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/GetDataFromSensor1.pid";
		system "/sbin/start-stop-daemon -S -x /usr/bin/nohup /scripts/work/sonstiges/GetDataFromSensor1 -m --pidfile /tmp/GetDataFromSensor1.pid >/dev/null 2>&1 &";
		exit 0;
	}

	return $DaliStart;
}

sub DaliWrite {
	my ($register, $wert) = @_;

	my $DaliStart = `/scripts/work/sonstiges/ModbusAbfrageSend Send $DaliID $Interface 57600 $register $wert`;
	chomp($DaliStart);

	if ($DaliStart eq "FF") {
		print "ERROR:FF\n";
		system "/scripts/work/2dbs/GoPlGoS CLIENTFRONTUPDATE \"$Sec~$ClientID~DaliInfoBack;DaliGwNichtErreichbar;$ARGV[0]\"";
		system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/GetDataFromSensor1.pid";
		system "/sbin/start-stop-daemon -S -x /usr/bin/nohup /scripts/work/sonstiges/GetDataFromSensor1 -m --pidfile /tmp/GetDataFromSensor1.pid >/dev/null 2>&1 &";
		exit 0;
	}

	return $DaliStart;
}

sub DaliQuerryAfterWrite {
    # Jetzt max. 20 Abfragen auf Register 1
    for (my $i = 0; $i < 20; $i++) {
        my $DaliQuery = DaliQuery(1);

        if ($DaliQuery eq "2") {
            # Noch in Bearbeitung → kurz warten und erneut probieren
            select(undef, undef, undef, 0.5);
            next;
        }
        elsif ($DaliQuery eq "3") {
            # Alles gut → Erfolg
            return 1;
        }
        elsif ($DaliQuery eq "4") {
            # Fehlerstatus → spezielle Behandlung
            print "ERROR:4\n";
	    system "/scripts/work/2dbs/GoPlGoS CLIENTFRONTUPDATE \"$Sec~$ClientID~DaliInfoStatusReg1;$ARGV[0];4\"";
            system "/sbin/start-stop-daemon -s 9 -K --pidfile /tmp/GetDataFromSensor1.pid";
            system "/sbin/start-stop-daemon -S -x /usr/bin/nohup /scripts/work/sonstiges/GetDataFromSensor1 -m --pidfile /tmp/GetDataFromSensor1.pid >/dev/null 2>&1 &";
            exit 0;
        }
        else {
            # Unerwarteter Wert → einfach zurückgeben
            return $DaliQuery;
        }
    }

    # Falls nach 20 Versuchen immer noch kein "3" oder "4" da ist
    return undef;
}

