Divoom Aurabox + Timebox + TimeboxEvo [Update, kommunizieren funktioniert]

Begonnen von schwatter, 25 Dezember 2017, 23:37:43

Vorheriges Thema - Nächstes Thema

schwatter


schwatter

Ok habs. Erst das in die Sequenzfiles,

require "/opt/fhem/divoom/lib.pl";

Und am Ende der lip.pl noch das,

1;


schwatter

Da meine Aurabox nur ein Setup für 12Std hatte, habe ich die Tage den Support angeschrieben.
Heute habe ich den Updater erhalten, Update dazu im ersten Post.

mumpitzstuff

#33
Woher hast du das Timebox Update? Auch von dort? Ich habe nur eine Timebox Mini. Funktioniert das Update da auch?

Leider kann man glaub nirgends die Firmware Version sehen, um zu prüfen, ob sich ein Update lohnt.

schwatter

Habe mich auf der Suche durch Youtube und Facebook gewühlt. Update, hab TimeboxMini auch gefunden.

schwatter

Update im ersten Post. Scriptsammlung auf Basis von mumpitzstuff Code.

mumpitzstuff

Bild Download habe ich angefangen, ist aber schon etwas komplizierter. Außerdem ist das Verfahren zwischen Timebox und Aurabox verschieden.

Danach werde ich mich mal ran setzen und sowas wie eine Befehlssammlung zusammen stellen auf Basis der Plain Kommandos. Bei denen kann man auch noch die ersten Zeichen entfernen, das ist nur die Länge der Nutzdaten, die man sich generieren kann. Ist mir leider erst gestern aufgefallen. Muss gucken wann ich wieder etwas Zeit finde weiter zu machen.

mumpitzstuff

Bild Download funktioniert für die Timebox, aber für die Aurabox komme ich nicht weiter. Die Perl Funktion wirft mir 3 8bit Werte aus und mir ist schleierhaft, wie ich das auf 4bit (16 Farben) runter rechnen soll. An der Stelle verstehe ich den Python Code auch nicht so richtig, da ich mit Python bisher wenig gemacht habe.

mumpitzstuff

- einige Funktionen wurden umbenannt
- plain nimmt jetzt nur noch Kommandos ohne Länge am Anfang an (die ersten 4 Zeichen)
- convertImageAB() (diese Funktion ist für die Aurabox), convertImageTB() konvertieren ein Bild in des Divoom Format. Ganz unten sieht man ein Beispiel. Kannst du mal bitte gucken, ob bei dir das Example Bild geladen wird (die Farbwerte stimmen wahrscheinlich noch nicht)? Das Example Bild findest du unter Images hier:

https://github.com/derHeinz/divoom-adapter

- resize funktioniert bei der Aurabox bisher leider nicht, da mir die verwendete Bibliothek ansonsten die Palette zerstört.

#!/usr/bin/perl
use strict;
use warnings;
use Net::Bluetooth;
use IO::Select;
use Imager;

sub listDevices();
sub connectDivoom($);
sub disconnectDivoom();
sub sendRaw($$);
sub sendPlain($$);
sub convertRawToPlain($);
sub convertImageTB($;$);
sub convertImageAB($;$);

my $socket;
my $TIMEBOX;

sub listDevices()
{
  print "Search for devices...\n\n"; 

  my $device_ref = get_remote_devices();
 
  foreach my $addr (keys %$device_ref)
  {
    print "Address: $addr Name: $device_ref->{$addr}\n";
  }

  print "done\n\n";
}

sub connectDivoom($)
{
  my $device = shift;
  my $ret;
  my $success = 0;

  print "Create RFCOMM client ($device)...\n";

  $socket = Net::Bluetooth->newsocket("RFCOMM");
  return $success unless(defined($socket));
 
  if (0 != $socket->connect($device, 4))
  {
    $socket->close();
    return $success;
  }

  $TIMEBOX = $socket->perlfh();
 
  sysread($TIMEBOX, $ret, 256);
  if (defined($ret))
  {
    $ret =~ s/[^[:print:]]//g;
    print "Device answer: $ret";

    if ('HELLO' eq $ret)
    {
      $success = 1;
    }
    else
    {
      close($TIMEBOX);
      $socket->close();
    }
  }
 
  print "\ndone\n\n";

  return $success;
}

sub disconnectDivoom()
{
  close($TIMEBOX);
  $socket->close();
}

sub sendRaw($$)
{
  my $data = shift;
  my $timeout = shift;
  my $ret;
  my $retry = 0;
  my $select = IO::Select->new($TIMEBOX);
 
  print "Send raw command: $data\n";

  $data =~ s/((?:[0-9a-fA-F]{2})+)/pack('H*', $1)/ge;
 
  do
  {
    syswrite($TIMEBOX, $data);

    if ($select->can_read(0.1))
    {
      sysread($TIMEBOX, $ret, 256);
      if (defined ($ret))
      {
        $ret = unpack('(H2)*', $ret);
        $ret =~ s/[^[:print:]]+//g;
        print "Device answer: $ret";
      }
    }

    $retry++;
  } while (($retry <= 3) && (!defined($ret) || '01' ne $ret));

  if ($retry > 3)
  {
    print "Failed!";
  }
  else
  {
    sleep($timeout);
  }

  print "\ndone\n\n";
}

sub sendPlain($$)
{
  my $data = shift;
  my $timeout = shift;
  my $crc = 0;
  my $ret;
  my $retry = 0;

  print "Send plain command: $data\n";

  # add length (length of data + length of checksum)
  $_ = (length($data) + 4) / 2;
  $data = sprintf("%02x", ($_ & 0xFF)).sprintf("%02x", (($_ >> 8) & 0xFF)).$data;

  # calculate crc
  while ($data =~ /(..)/g)
  {
    $crc += hex($1);
  }

  # add crc
  $data .= sprintf("%02x", ($crc & 0xFF)).sprintf("%02x", (($crc >> 8) & 0xFF)); 

  # escape data
  $data =~ s/(01|02|03)(?{ if (0 == ($-[0] & 1)) {'030'.(3+$1)} else {$1} })/$^R/g;

  # add prefix and postfix
  $data = '01'.$data.'02';

  print "Generated raw command: $data\n";

  sendRaw($data, $timeout);
}

sub convertRawToPlain($)
{
  my $data = shift;

  print $data."\n";

  # remove prefix and postfix
  $data = substr($data, 2, -2);

  # unescape data
  $data =~ s/(03(04|05|06))(?{ if (0 == ($-[0] & 1)) {'0'.($2-3)} else {$1} })/$^R/g;
 
  #remove length
  $data = substr($data, 4);

  # remove checksum
  $data = substr($data, 0, -4);

  print $data."\n";

  return $data;
}

sub convertImageTB($;$)
{
  my $file = shift;
  my $size = shift;
  my @imgData = (0);
  my $image = Imager->new;
 
  $size = 11 if (!defined($size));
  $image->read(file=>$file);
 
  if (!$@)
  {
    my ($r, $g, $b, $a);
    my $flicflac = 0;   
    my $imageResized = $image->scaleX(pixels=>$size)->scaleY(pixels=>$size);

    for (my $y = 0; $y < $size; $y++)
    {
      for (my $x = 0; $x < $size; $x++)
      {
        ($r, $g, $b, $a) = $imageResized->getpixel(x=>$x, y=>$y)->rgba();
       
        if (0 == $flicflac)
        {
          if ($a > 32)
          {
            $imgData[-1] = (($r & 0xF0) >> 4) + ($g & 0xF0);
            push(@imgData, (($b & 0xF0) >> 4));
          }
          else
          {
            $imgData[-1] = 0;
            push(@imgData, 0);
          }

          $flicflac = 1;
        }
        else
        {
          if ($a > 32)
          {
            $imgData[-1] += ($r & 0xF0);
            push(@imgData, (($g & 0xF0) >> 4) + ($b & 0xF0));
          }
          else
          {
            $imgData[-1] += 0;
            push(@imgData, 0);
          }
          push(@imgData, 0);

          $flicflac = 0;
        }
      }
    }
  }

  $_ = '';
  foreach my $byte (@imgData)
  {
    $_ .= sprintf("%02x", ($byte & 0xFF));
  }

  return $_;
}

sub convertImageAB($;$)
{
  my $file = shift;
  my $size = shift;
  my @imgData = ();
  my $image = Imager->new;
  #my %color = {0 => 0, 1 => 1, 2 => 2, 3 => 11, 5 => 5, 6 => 2, 7 => 5, 9 => 1, 10 => 2, 11 => 3, 12 => 4, 14 => 6, 15 => 7};

  $size = 10;# if (!defined($size));
  $image->read(file=>$file);

  if (!$@)
  {
    my $flicflac = 0;
    #my $imageResized = $image->scaleX(pixels=>$size)->scaleY(pixels=>$size);

    for (my $y = 0; $y < $size; $y++)
    {
      for (my $x = 0; $x < $size; $x++)
      {
        if (0 == $flicflac)
        {
          push(@imgData, $image->findcolor(color=>$image->getpixel(x=>$x, y=>$y)));

          $flicflac = 1;
        }
        else
        {
          $imgData[-1] += ($image->findcolor(color=>$image->getpixel(x=>$x, y=>$y)) << 4);

          $flicflac = 0;
        }
      }
    }
  }

  $_ = '';
  foreach my $byte (@imgData)
  {
    $_ .= sprintf("%02x", ($byte & 0xFF));
  }

  return $_;
}


my $example = convertImageAB('example.bmp', 10);
my $skull = convertImageTB('skull.png', 11);

if (connectDivoom('11:75:58:4F:A1:CB'))
{
  #sendPlain('4509', 5);
  #sendPlain('4508', 5);
  #sendPlain('4507', 5);
  #sendPlain('4506', 5);
  #sendPlain('4505', 5);
  #sendPlain('4504', 5);
  #sendPlain('4503', 5);
  #sendPlain('4502', 5);
  #sendPlain('4501', 5);
  sendPlain('4500', 5);
  sendPlain('44000A0A04'.$skull, 5);
  sendPlain('44000A0A04'.$example, 5);
  disconnectDivoom();
}

schwatter

#39
Suche den install für Imager. Läuft das über Cpan?

edit:

Ok, Imager hab ich.


sudo cpan install Imager


edit2:

Nachdem ich alle Funktionen zur Timebox auskommentiert habe, funktioniert es. Das Example wird geladen. Zur Farbe, könnte passen. Ich teste weiter.

edit3:

Versuche ich das Example durch ein anderes zu ersetzen bekomme ich.


root@raspiFhem:/opt/fhem/divoom# perl divoom.pl
Modification of non-creatable array value attempted, subscript -1 at divoom.pl line 274.


edit4:
Das die Farbwerte nicht stimmen kommt hin. Ich habe jetzt dieses Bild einfach mal Probiert.

https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRESCVw2mTJM-WFx-9YBdk9Qy7gHIDfE7nnXL7fhhJzS8ihvVtQ5Q

Einfach ein rename von .png auf bmp. Das wird sauber angezeigt. Allerdings nicht in blau. Farbe ist dann rot.

schwatter

#40
Ich habe mal ein Example.bmp erstellt. Ganz aussagekräftig ist das aber auch nicht, da die Farben nicht 1zu1 anders sind.

Das Bild hat von oben nach unten die Farben:

schwarz,blau,rot,gelb,grün,rot,gelb,blau,gelb,schwarz


als Ausgabe auf der Box kam die Reihenfolge:


schwarz,grün,gelb,blau,rot,gelb,blau,grün,blau,schwarz


schwatter

Nachdem ich jetzt das Feuerwerk von 4bit auf 8bit erhöht habe, läuft das auch durch.


my $firework1 = convertImageAB('firework1.bmp', 10);
my $firework2 = convertImageAB('firework2.bmp', 10);
my $firework3 = convertImageAB('firework3.bmp', 10);
my $firework4 = convertImageAB('firework4.bmp', 10);
my $firework5 = convertImageAB('firework5.bmp', 10);
my $firework6 = convertImageAB('firework6.bmp', 10);
my $firework7 = convertImageAB('firework7.bmp', 10);
my $firework8 = convertImageAB('firework8.bmp', 10);

if (connectDivoom('XX:XX:XX:XX:XX:XX'))
{
  sendPlain('44000A0A04'.$firework1, 1);
  sendPlain('44000A0A04'.$firework2, 1);
  sendPlain('44000A0A04'.$firework3, 1);
  sendPlain('44000A0A04'.$firework4, 1);
  sendPlain('44000A0A04'.$firework5, 1);
  sendPlain('44000A0A04'.$firework6, 1);
  sendPlain('44000A0A04'.$firework7, 1);
  sendPlain('44000A0A04'.$firework8, 1);
  disconnectDivoom();
}


mumpitzstuff

Ja. Habe ja gesagt, das die Farbwerte noch nicht passen werden. Wollte nur schon mal wissen, ob grundsätzlich was zu sehen ist. Ich schau mir das dahingehend noch mal an. Die Python Lib auf Github scheint übrigens nur mit einer ganz bestimmten Palette zu funktionieren, da einfach ein festes Mapping der Farbwerte implementiert ist. Ich mach mal das Mapping rein und dann schauen wir weiter.

schwatter

Hab ich auch so aufgenommen. Hab einfach wild getestet
und das ganze hier niedergeschrieben. Vielleicht bleibt was
hängen, was doch mal hilft. Bist auf dem richtigen Weg  :)

mumpitzstuff

#44
Die Routine für die Aurabox braucht immer eine Farbpalette mit exakt 16 Farben. Wahrscheinlich kam der Fehler daher. Bisher wird nichts groß abgefangen, deshalb kann das Script dann auch abstürzen. Funktion schlägt erst einmal Robustheit...

Habe noch mal nachgesehen. Die Palette selbst kann tatsächlich größer sein. In dem Example z.B. scheinen aber nur 10 Farben verwendet zu werden.