diff --git a/fhem/CHANGED b/fhem/CHANGED
index 480eb73e3..8354aeb87 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -38,6 +38,7 @@
- feature: added support for UV sensors in TRX_LIGHT using RFXtrx433 (Willi Herzig)
- feature: added on-till and on-timer for set in TRX_LIGHT using RFXtrx433 (Willi Herzig)
- feature: generate devices with hexcodes as state for unknown types in TRX_ELSE using RFXtrx433 (Willi Herzig)
+ - feature: new modules 10_OWServer.pm and 11_OWDevice.pm to interface with OWFS
- 2012-10-28 (5.3)
- feature: added functions trim, ltrim, rtrim, UntoggleDirect,
diff --git a/fhem/FHEM/10_OWServer.pm b/fhem/FHEM/10_OWServer.pm
new file mode 100644
index 000000000..4977ab733
--- /dev/null
+++ b/fhem/FHEM/10_OWServer.pm
@@ -0,0 +1,268 @@
+# $Id: $
+################################################################
+#
+# Copyright notice
+#
+# (c) 2012 Copyright: Dr. Boris Neubert
+# omega at online dot de
+#
+# This file is part of fhem.
+#
+# Fhem is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fhem is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with fhem. If not, see .
+#
+################################################################################
+
+package main;
+
+use strict;
+use warnings;
+# this must be the latest OWNet from
+# http://owfs.cvs.sourceforge.net/viewvc/owfs/owfs/module/ownet/perl5/OWNet/lib/OWNet.pm
+# the version at CPAN is outdated and malfunctioning as at 2012-12-19
+use OWNet;
+
+#####################################
+sub
+OWServer_Initialize($)
+{
+ my ($hash) = @_;
+
+# Provider
+ $hash->{WriteFn}= "OWServer_Write";
+ $hash->{ReadFn} = "OWServer_Read";
+ $hash->{Clients}= ":OWDevice:";
+
+# Consumer
+ $hash->{DefFn} = "OWServer_Define";
+ $hash->{UndefFn} = "OWServer_Undef";
+ $hash->{GetFn} = "OWServer_Get";
+# $hash->{SetFn} = "OWServer_Set";
+# $hash->{AttrFn} = "OWServer_Attr";
+ $hash->{AttrList}= "loglevel:0,1,2,3,4,5";
+}
+
+#####################################
+sub
+OWServer_Define($$)
+{
+ my ($hash, $def) = @_;
+
+ my @a = split("[ \t]+", $def, 3);
+ my $name = $a[0];
+ if(@a < 3) {
+ my $msg = "wrong syntax for $name: define OWServer ";
+ Log 2, $msg;
+ return $msg;
+ }
+
+ my $protocol = $a[2];
+
+ OWServer_CloseDev($hash);
+
+ $hash->{fhem}{Protocol}= $protocol;
+
+ OWServer_OpenDev($hash, $protocol);
+ return undef;
+}
+
+
+#####################################
+sub
+OWServer_Undef($$)
+{
+ my ($hash, $arg) = @_;
+ my $name = $hash->{NAME};
+
+ foreach my $d (sort keys %defs) {
+ if(defined($defs{$d}) &&
+ defined($defs{$d}{IODev}) &&
+ $defs{$d}{IODev} == $hash)
+ {
+ my $lev = ($reread_active ? 4 : 2);
+ Log GetLogLevel($name,$lev), "deleting OWServer for $d";
+ delete $defs{$d}{IODev};
+ }
+ }
+
+ OWServer_CloseDev($hash);
+ return undef;
+}
+
+#####################################
+sub
+OWServer_CloseDev($)
+{
+ my ($hash) = @_;
+
+ return unless(defined($hash->{fhem}{owserver}));
+ delete $hash->{fhem}{owserver};
+
+}
+
+########################
+sub
+OWServer_OpenDev($$)
+{
+ my ($hash, $protocol) = @_;
+ my $name = $hash->{NAME};
+
+ Log 4, "$name: Opening connection to OWServer $protocol...";
+ my $owserver= OWNet->new($protocol);
+ if($owserver) {
+ Log 4, "$name: Successfully connected to $protocol.";
+ $hash->{fhem}{owserver}= $owserver;
+ DoTrigger($name, "CONNECTED") if($owserver);
+ }
+ return $owserver
+}
+
+#####################################
+sub
+OWServer_DoInit($)
+{
+ my $hash = shift;
+ my $name = $hash->{NAME};
+ $hash->{STATE} = "Initialized" if(!$hash->{STATE});
+
+ return undef;
+}
+
+#####################################
+sub
+OWServer_Read($@)
+{
+ my ($hash,$path)= @_;
+
+ return undef unless(defined($hash->{fhem}{owserver}));
+ return $hash->{fhem}{owserver}->read($path);
+}
+
+#####################################
+sub
+OWServer_Write($@)
+{
+ my ($hash,$path,$value)= @_;
+
+ return undef unless(defined($hash->{fhem}{owserver}));
+ return $hash->{fhem}{owserver}->write($path,$value);
+}
+
+
+#####################################
+sub
+OWServer_Get($@)
+{
+ my ($hash, @a) = @_;
+
+ my $name = $a[0];
+
+ return "$name: get needs at least one parameter" if(@a < 2);
+
+ my $cmd= $a[1];
+ #my $arg = ($a[2] ? $a[2] : "");
+ #my @args= @a; shift @args; shift @args;
+
+ my $owserver= $hash->{fhem}{owserver};
+
+ if($cmd eq "devices") {
+ my @dir= split(",", $owserver->dir());
+ my @devices= grep { m/^\/\d\d\.\d+$/ } @dir;
+ my $ret;
+ for my $device (@devices) {
+ $ret .= substr($device,1) . " " . $owserver->read($device . "/type") . "\n";
+ }
+ return $ret;
+ } else {
+ return "Unknown argument $cmd, choose one of devices"
+ }
+
+}
+
+#####################################
+
+
+1;
+
+
+=pod
+=begin html
+
+
+OWServer
+
+
+
+ Define
+
+ define <name> OWDevice <protocol>
+
+
+ Defines a logical OWServer device. OWServer is the server component of the
+ 1-Wire Filesystem. It serves as abstraction layer
+ for any 1-wire devices on a host. <protocol> has
+ format <hostname>:<port>. For details see
+ owserver documentation.
+
+ You need OWNet.pm from owfs.org. Just drop it into your FHEM
+ folder alongside the 10_OWServer.pm
module. As at 2012-12-23 the OWNet module
+ on CPAN has an issue which renders it useless for remote connections.
+
+ The actual 1-wire devices are defined as OWDevice devices.
+
+ This module is completely unrelated to the 1-wire modules with names all in uppercase.
+
+ Examples:
+
+ define myLocalOWServer OWServer localhost:4304
+ define myRemoteOWServer OWServer raspi:4304
+
+
+
+
+
+ Set
+
+
+
+
+
+ Get
+
+ get <name> devices
+
+ Lists the addresses and types of all 1-wire devices provided by the owserver.
+
+
+
+
+
+
+ Attributes
+
+
+
+
+
+
+
+
+=end html
+=cut
diff --git a/fhem/FHEM/11_OWDevice.pm b/fhem/FHEM/11_OWDevice.pm
new file mode 100644
index 000000000..f489658c2
--- /dev/null
+++ b/fhem/FHEM/11_OWDevice.pm
@@ -0,0 +1,355 @@
+# $Id: $
+##############################################################################
+#
+# 11_OWDevice.pm
+# Copyright by Dr. Boris Neubert
+# e-mail: omega at online dot de
+#
+# This file is part of fhem.
+#
+# Fhem is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fhem is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with fhem. If not, see .
+#
+##############################################################################
+
+
+package main;
+
+use strict;
+use warnings;
+
+
+###################################
+sub
+OWDevice_Initialize($)
+{
+ my ($hash) = @_;
+
+ $hash->{GetFn} = "OWDevice_Get";
+ $hash->{SetFn} = "OWDevice_Set";
+ $hash->{DefFn} = "OWDevice_Define";
+
+ $hash->{AttrList} = "trimvalues loglevel:0,1,2,3,4,5";
+}
+
+###################################
+# return array
+# 1st element: interface
+# 2nd element: array of getters/readings
+# 3rd element: array of setters/readings
+# 4th element: array of readings to be periodically updated
+# the value of the first reading in getters is written to state
+sub
+OWDevice_GetDetails($) {
+
+ my ($hash)= @_;
+ my $interface= "";
+ my @getters= qw(address alias family id power type);
+ my @setters= qw(alias);
+ my @polls;
+
+ # below we use shift such that the potentially
+ # more important values get listed first and
+ # that the first reading in getters could be
+ # defined (it is shown in the STATE).
+
+ # http://owfs.sourceforge.net/family.html
+ my $family= substr($hash->{fhem}{address}, 0, 2);
+ if($family eq "10") {
+ # 18S20 high precision digital thermometer
+ unshift @getters, qw(temperature templow temphigh);
+ unshift @setters, qw(templow temphigh);
+ unshift @polls, qw(temperature);
+ $interface= "temperature";
+ } elsif($family eq "reserved") {
+ # reserved for other devices
+ };
+ # http://perl-seiten.homepage.t-online.de/html/perl_array.html
+ return ($interface, \@getters, \@setters, \@polls);
+}
+
+###################################
+# This could be IORead in fhem, But there is none.
+# Read http://forum.fhem.de/index.php?t=tree&goto=54027&rid=10#msg_54027
+# to find out why.
+sub
+OWDevice_ReadFromServer($@)
+{
+ my ($hash, @a) = @_;
+
+ my $dev = $hash->{NAME};
+ return if(IsDummy($dev) || IsIgnored($dev));
+ my $iohash = $hash->{IODev};
+ if(!$iohash ||
+ !$iohash->{TYPE} ||
+ !$modules{$iohash->{TYPE}} ||
+ !$modules{$iohash->{TYPE}}{ReadFn}) {
+ Log 5, "No I/O device or ReadFn found for $dev";
+ return;
+ }
+
+ no strict "refs";
+ my $ret = &{$modules{$iohash->{TYPE}}{ReadFn}}($iohash, @a);
+ use strict "refs";
+ return $ret;
+}
+
+###################################
+sub
+OWDevice_ReadValue($$) {
+
+ my ($hash,$reading)= @_;
+
+ my $address= $hash->{fhem}{address};
+ my $value= OWDevice_ReadFromServer($hash, "/$address/$reading");
+ $value= trim($value) if(AttrVal($hash,"trimvalues",1));
+ my @getters= @{$hash->{fhem}{getters}};
+ Debug join(",", @getters);
+ Debug $getters[0];
+ $hash->{STATE}= $value if($reading eq $getters[0]);
+
+ return $value;
+}
+
+###################################
+sub
+OWDevice_WriteValue($$$) {
+
+ my ($hash,$reading,$value)= @_;
+
+ my $address= $hash->{fhem}{address};
+ IOWrite($hash, "/$address/$reading", $value);
+ return $value;
+}
+
+###################################
+sub
+OWDevice_UpdateValues($) {
+
+ my ($hash)= @_;
+
+ my @polls= @{$hash->{fhem}{polls}};
+ if($#polls>=0) {
+ my $address= $hash->{fhem}{address};
+ readingsBeginUpdate($hash);
+ foreach my $reading (@polls) {
+ my $value= OWDevice_ReadValue($hash,$reading);
+ readingsBulkUpdate($hash,$reading,$value);
+ }
+ readingsEndUpdate($hash,1);
+ }
+ InternalTimer(gettimeofday()+$hash->{fhem}{interval}, "OWDevice_UpdateValues", $hash, 0)
+ if(defined($hash->{fhem}{interval}));
+
+}
+
+###################################
+sub
+OWDevice_Get($@)
+{
+ my ($hash, @a)= @_;
+
+ my $name= $hash->{NAME};
+ return "get $name needs one argument" if(int(@a) != 2);
+ my $cmdname= $a[1];
+ my @getters= @{$hash->{fhem}{getters}};
+ if($cmdname ~~ @getters) {
+ my $value= OWDevice_ReadValue($hash, $cmdname);
+ readingsSingleUpdate($hash,$cmdname,$value,1);
+ return $value;
+ } else {
+ return "Unknown argument $cmdname, choose one of " . join(" ", @getters);
+ }
+}
+
+#############################
+sub
+OWDevice_Set($@)
+{
+ my ($hash, @a)= @_;
+
+ my $name= $hash->{NAME};
+ my $cmdname= $a[1];
+ my $value= $a[2];
+ my @setters= @{$hash->{fhem}{setters}};
+ if($cmdname ~~ @setters) {
+ return "set $name needs two arguments" if(int(@a) != 3);
+ OWDevice_WriteValue($hash,$cmdname,$value);
+ readingsSingleUpdate($hash,$cmdname,$value,1);
+ return undef;
+ } else {
+ return "Unknown argument $cmdname, choose one of " . join(" ", @setters);
+ }
+}
+
+#############################
+sub
+OWDevice_Define($$)
+{
+ my ($hash, $def) = @_;
+ my @a = split("[ \t]+", $def);
+
+ return "Usage: define OWDevice [interval]" if($#a < 3 || $#a > 4);
+ my $name= $a[0];
+
+ AssignIoPort($hash);
+ if(defined($hash->{IODev}->{NAME})) {
+ Log 3, "$name: I/O device is " . $hash->{IODev}->{NAME};
+ } else {
+ Log 1, "$name: no I/O device";
+ }
+
+ $hash->{fhem}{address}= $a[2];
+ if($#a == 3) {
+ $hash->{fhem}{interval}= $a[3];
+ Log 5, "$name: polling every $a[3] seconds";
+ }
+ my ($interface, $gettersref, $settersref, $pollsref)= OWDevice_GetDetails($hash);
+ my @getters= @{$gettersref};
+ my @setters= @{$settersref};
+ my @polls= @{$pollsref};
+ if($interface ne "") {
+ $hash->{fhem}{interfaces}= $interface;
+ Log 5, "$name: interfaces: $interface";
+ }
+ $hash->{fhem}{getters}= $gettersref;
+ Log 5, "$name: getters: " . join(" ", @getters);
+ $hash->{fhem}{setters}= $settersref;
+ Log 5, "$name: setters: " . join(" ", @setters);
+ $hash->{fhem}{polls}= $pollsref;
+ Log 5, "$name: polls: " . join(" ", @polls);
+
+ OWDevice_UpdateValues($hash) if(defined($hash->{fhem}{interval}));
+
+ return undef;
+}
+###################################
+
+1;
+
+###################################
+=pod
+=begin html
+
+
+OWDevice
+
+
+
+ Define
+
+ define <name> OWDevice <address> [<interval>]
+
+
+ Defines a 1-wire device. The 1-wire device is identified by its <address>. It is
+ served by the most recently defined OWServer.
+
+
+ If <interval> is given, the OWServer is polled every <interval> seconds for
+ a subset of readings.
+
+
+ OWDevice is a generic device. Its characteristics are retrieved at the time of the device's
+ definition. The available readings that you can get or set as well as those that are
+ regularly retrieved by polling can be seen when issuing the
+ list <name>
command.
+
+ This module is completely unrelated to the 1-wire modules with names all in uppercase.
+
+
+ Example:
+
+
+ define myOWServer localhost:4304
+ get myOWServer devices
+ 10.487653020800 DS18S20
+ define myT1 10.487653020800
+ list myT1 10.487653020800
+ Internals:
+ ...
+ Readings:
+ 2012-12-22 20:30:07 temperature 23.1875
+ Fhem:
+ ...
+ getters:
+ address
+ alias
+ family
+ id
+ power
+ type
+ temperature
+ templow
+ temphigh
+ polls:
+ temperature
+ setters:
+ alias
+ templow
+ temphigh
+ ...
+
+
+
+
+
+
+ Set
+
+ set <name> <reading> <value>
+
+ Sets <reading> to <value> for the 1-wire device <name>. The permitted values are defined by the underlying
+ 1-wire device type.
+
+ Example:
+
+
+
+
+
+
+ Get
+
+ get <name> <reading> <value>
+
+ Gets <reading> for the 1-wire device <name>. The permitted values are defined by the underlying
+ 1-wire device type.
+
+ Example:
+
+
+
+
+
+
+ Attributes
+
+
+
+
+
+
+
+
+
+=end html
+=cut