package FHEM::BlueLinkVehicle; use strict; use warnings; use JSON; use Time::Piece; sub Initialize { my ($hash) = @_; $hash->{DefFn} = "BlueLinkVehicle_Define"; $hash->{SetFn} = "BlueLinkVehicle_Set"; $hash->{GetFn} = "BlueLinkVehicle_Get"; $hash->{AttrList} = "vin IODev"; } sub BlueLinkVehicle_Define { my ($hash, $def) = @_; my @args = split("[ \t]+", $def); return "Usage: define BlueLinkVehicle " if (@args < 4); $hash->{VIN} = $args[2]; my $parent = $args[3]; $hash->{IODev} = $defs{$parent}; return "Parent device $parent not found" unless defined $hash->{IODev}; return; } sub BlueLinkVehicle_Set { my ($hash, $name, $cmd, @args) = @_; return "\"set $name\" needs at least one argument" unless defined $cmd; if ($cmd eq "update") { return BlueLinkVehicle_Update($hash); } return "Unknown argument $cmd, choose one of update"; } sub BlueLinkVehicle_Get { my ($hash, $name, $cmd, @args) = @_; return "\"get $name\" needs at least one argument" unless defined $cmd; if ($cmd eq "soc") { return ReadingsVal($name, "SoC", "Unknown") . " %"; } elsif ($cmd eq "range") { return ReadingsVal($name, "Range", "Unknown") . " km"; } elsif ($cmd eq "status") { return ReadingsVal($name, "Status", "Unknown"); } return "Unknown argument $cmd, choose one of soc range status"; } sub BlueLinkVehicle_Update { my ($hash) = @_; my $name = $hash->{NAME}; my $parent = $hash->{IODev}; my $vin = $hash->{VIN}; return "Parent module not found" unless $parent; return "VIN not defined" unless $vin; # Anfrage an das Hauptmodul senden (IOWrite) IOWrite($parent, "getVehicleStatus", $vin); return "Request sent to parent module."; } sub BlueLinkVehicle_ParseTime { my ($time_string) = @_; return unless $time_string; my $format = "%Y%m%d%H%M%S %z"; my $t = Time::Piece->strptime($time_string . " +0100", $format); return $t->strftime("%Y-%m-%d %H:%M:%S"); } sub BlueLinkVehicle_Receive { my ($hash, $data) = @_; my $name = $hash->{NAME}; my $json = eval { decode_json($data) }; return "Invalid JSON data received" if $@; if ($json->{vin} && $json->{vin} eq $hash->{VIN}) { my $status = $json->{status}; my $soc = $status->{EvStatus}->{BatteryStatus} // "Unknown"; my $range = $status->{EvStatus}->{DrvDistance}->[0]->{RangeByFuel}->{EvModeRange}->{Value} // "Unknown"; my $charging = $status->{EvStatus}->{BatteryCharge} ? "Charging" : "Not Charging"; my $updated = BlueLinkVehicle_ParseTime($status->{Time}) // "Unknown"; readingsBeginUpdate($hash); readingsBulkUpdate($hash, "SoC", $soc); readingsBulkUpdate($hash, "Range", $range); readingsBulkUpdate($hash, "Status", $charging); readingsBulkUpdate($hash, "LastUpdate", $updated); readingsEndUpdate($hash, 1); return "Vehicle data updated."; } return "VIN mismatch - ignoring data."; } 1;