FHEM Forum

FHEM - Entwicklung => FHEM Development => Thema gestartet von: justme1968 am 13 September 2015, 22:59:01

Titel: device 'simulator'
Beitrag von: justme1968 am 13 September 2015, 22:59:01
da ich schon öfter in die verlegenheit gekommen bin ein bestimmtes device aus dem setup eines anwenders nachzustellen und das jetzt gerade mit der homebridge/siri integration wieder akut geworden ist habe ich mir die folgenden beiden kleinen hilfsroutinen geschrieben um aus einer jsonlist2 die der anwender posten kann eine möglichst exakte kopie dieses devices wieder herzustellen.

diese kopie kann auf einem dummy basieren oder das tatsächliche device modul verwenden. im dummy fall wird versuch über die setList und readingList attribute auch das aussehen und verhalten unter im webfrontend ein wenig nachzubilden. durch ein paar optionale parameter lassen sich dinge wie device name, die übername von internals, readings und attributen sowie die setList/readingList beeinflussen. die json daten können direkt als string übergeben oder aus einem file gelesen werden.

es gibt zwei routinen die aufeinander aufbauen:
das ganze ist natürlich nicht perfekt aber für viele fälle bei denen es 'nur' um frontend entwicklung geht eine recht gute näherung. vielleicht nützt es ja noch anderen um beim entwickeln bestimmte szenarien und devices nachzustellen.

eine mögliche verbesserungen könnten noch sein einen readingsProxy statt des normalen dummy zu verwenden um die set kommandos realistischer nachzubilden und auch noch mögliche get kommandos zu simulieren.

gruss
  andre

sub
jsonlist2device($;$)
{
  my($json, $defaults) = @_;

  if( $json !~ m/^\s*{.*}\s*$/ ) {
    local $/ = undef;
    open FILE, $json or die "Couldn't open file: $!";
    binmode FILE;
    $json = <FILE>;
    close FILE;
  }

  use JSON;
  my $decoded = decode_json($json);

  foreach my $device (@{$decoded->{Results}}) {
    my $name = $device->{Internals}->{NAME};
    my $type = $device->{Internals}->{TYPE};
    my $def = $device->{Internals}->{DEF};
    $def = "" if( !defined($def) );

    $name = $defaults->{NAME} if( $defaults->{NAME} );
    $name =~ s/#/$device->{Internals}->{NAME}/;
    $type = $defaults->{TYPE} if( $defaults->{TYPE} );
    $def = $defaults->{DEF} if( defined($defaults->{DEF}) );

    $device->{Internals} = $defaults->{Internals} if( defined($defaults->{Internals}) );
    $device->{Readings} = $defaults->{Readings} if( defined($defaults->{Readings}) );
    $device->{Attributes} = $defaults->{Attributes} if( defined($defaults->{Attributes}) );
    $device->{PossibleSets} = $defaults->{PossibleSets} if( exists($defaults->{PossibleSets}) );

    my $ret = CommandDefine(undef, "$name $type $def");
    if( $ret ) {
      Log3 undef, 1, "jsonlist2device: $ret" if( $ret );
      return undef;
    }   

    foreach my $internal (keys %{$device->{Internals}} ) {
      next if( $internal eq 'NAME' );
      next if( $internal eq 'TYPE' );
      next if( $internal eq 'DEF' );
      next if( $internal eq 'CFGFN' );
      $defs{$name}->{$internal} = $device->{Internals}->{$internal};
    }   

    my $readingList;
    foreach my $reading (keys %{$device->{Readings}} ) {
      $defs{$name}->{READINGS}->{$reading} = { VAL => $device->{Readings}->{$reading}->{Value},
                                               TIME => $device->{Readings}->{$reading}->{Time} };

      $readingList .= ' ' if( $readingList );
      $readingList .= $reading;
    }   

    foreach my $attr (keys %{$device->{Attributes}} ) {
      $attr{$name}->{$attr} = $device->{Attributes}->{$attr};
    }   

    if( $type eq 'dummy'
        && $device->{PossibleSets}
        && !defined( $attr{$name}->{setList}) ) {
      $attr{$name}->{setList} = $device->{PossibleSets};

      if($readingList
          && !defined( $attr{$name}->{readingList}) ) {
        $attr{$name}->{readingList} = $readingList;
      }   
    }   

  }
}

sub
jsonlist2dummy($;$)
{
  my($json,$name) = @_;

  $name = '#FromJson' if( !$name );

  jsonlist2device( $json, { TYPE => 'dummy', NAME => $name, DEF => '' } );

}