mirror of https://github.com/lumapu/ahoy.git
7 changed files with 265 additions and 208 deletions
@ -0,0 +1,186 @@ |
|||||
|
|
||||
|
package main; |
||||
|
|
||||
|
use strict; |
||||
|
use warnings; |
||||
|
use DevIo; # load DevIo.pm if not already loaded |
||||
|
|
||||
|
# called upon loading the module MY_MODULE |
||||
|
sub AHOYUL_Initialize($) |
||||
|
{ |
||||
|
my ($hash) = @_; |
||||
|
|
||||
|
$hash->{DefFn} = "ahoyUL_Define"; |
||||
|
$hash->{UndefFn} = "ahoyUL_Undef"; |
||||
|
$hash->{SetFn} = "ahoyUL_Set"; |
||||
|
$hash->{ReadFn} = "ahoyUL_Read"; |
||||
|
$hash->{ReadyFn} = "ahoyUL_Ready"; |
||||
|
|
||||
|
$hash->{ParseFn} = "ahoyUL_Parse"; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
# called when a new definition is created (by hand or from configuration read on FHEM startup) |
||||
|
sub ahoyUL_Define($$) |
||||
|
{ |
||||
|
my ($hash, $def) = @_; |
||||
|
my @a = split("[ \t]+", $def); |
||||
|
|
||||
|
my $name = $a[0]; |
||||
|
|
||||
|
# $a[1] is always equals the module name "MY_MODULE" |
||||
|
|
||||
|
# first argument is a serial device (e.g. "/dev/ttyUSB0@57600,8,N,1") |
||||
|
my $dev = $a[2]; |
||||
|
|
||||
|
return "no device given" unless($dev); |
||||
|
|
||||
|
# close connection if maybe open (on definition modify) |
||||
|
DevIo_CloseDev($hash) if(DevIo_IsOpen($hash)); |
||||
|
|
||||
|
# add a default baud rate (9600), if not given by user |
||||
|
$dev .= '@57600,8,N,1' if(not $dev =~ m/\@\d+$/); |
||||
|
|
||||
|
# set the device to open |
||||
|
$hash->{DeviceName} = $dev; |
||||
|
|
||||
|
# open connection with custom init function |
||||
|
my $ret = DevIo_OpenDev($hash, 0, "ahoyUL_Init"); |
||||
|
|
||||
|
return undef; |
||||
|
} |
||||
|
|
||||
|
# called when definition is undefined |
||||
|
# (config reload, shutdown or delete of definition) |
||||
|
sub ahoyUL_Undef($$) |
||||
|
{ |
||||
|
my ($hash, $name) = @_; |
||||
|
|
||||
|
# close the connection |
||||
|
DevIo_CloseDev($hash); |
||||
|
|
||||
|
return undef; |
||||
|
} |
||||
|
|
||||
|
# called repeatedly if device disappeared |
||||
|
sub ahoyUL_Ready($) |
||||
|
{ |
||||
|
my ($hash) = @_; |
||||
|
|
||||
|
# try to reopen the connection in case the connection is lost |
||||
|
return DevIo_OpenDev($hash, 1, "ahoyUL_Init"); |
||||
|
} |
||||
|
|
||||
|
# called when data was received |
||||
|
sub ahoyUL_Read($) |
||||
|
{ |
||||
|
my ($hash) = @_; |
||||
|
my $name = $hash->{NAME}; |
||||
|
|
||||
|
# read the available data |
||||
|
my $buf = DevIo_SimpleRead($hash); |
||||
|
# stop processing if no data is available (device disconnected) |
||||
|
return if(!defined($buf)); |
||||
|
#Log3 $name, 5, "ahoyUL ($name) - received: $buf"; |
||||
|
|
||||
|
my $pandata = $hash->{PARTIAL}; |
||||
|
Log3 $name, 5, "ahoyUL/RAW: $pandata + $buf"; |
||||
|
$pandata .= $buf; |
||||
|
|
||||
|
while ( $pandata =~ m/\n/ ) { # while-loop as long as "\n" in $pandata |
||||
|
my $rmsg; |
||||
|
( $rmsg, $pandata ) = split( "\n", $pandata, 2 ); |
||||
|
$rmsg =~ s/\r//; # substitution, replace "\r" by nothing |
||||
|
ahoyUL_Parse( $hash, $hash, $name, $rmsg ) if ($rmsg); |
||||
|
} |
||||
|
$hash->{PARTIAL} = $pandata; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
# called when one line of data was received |
||||
|
sub ahoyUL_Parse($$$$) |
||||
|
{ |
||||
|
my ( $hash, $iohash, $name, $rmsg) = @_; |
||||
|
Log3 $name, 3, "ahoyUL: $rmsg"; |
||||
|
|
||||
|
if($rmsg =~ m/rMAC/) { |
||||
|
# handle rmac responses |
||||
|
|
||||
|
|
||||
|
} elsif($rmsg =~ m/payload/) { |
||||
|
# payload |
||||
|
|
||||
|
|
||||
|
} elsif($rmsg =~ m/ch00/) { |
||||
|
# AC channel |
||||
|
readingsBeginUpdate($hash); |
||||
|
readingsBulkUpdateIfChanged($hash, "myPV1", $rmsg , 1); |
||||
|
readingsEndUpdate($hash, 1); |
||||
|
|
||||
|
} elsif($rmsg =~ m/ch0[1-4]/) { |
||||
|
# one DC channel |
||||
|
readingsBeginUpdate($hash); |
||||
|
readingsBulkUpdateIfChanged($hash, "myPV1", $rmsg , 1); |
||||
|
readingsEndUpdate($hash, 1); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
# called if set command is executed |
||||
|
sub ahoyUL_Set($$@) |
||||
|
{ |
||||
|
my ($hash, $name, @params) = @_; |
||||
|
#my @a = split("[ \t]+", @params); |
||||
|
|
||||
|
return "ahoyul_set needs at least a command" if(@params < 1); |
||||
|
my $cmd = $params[0]; |
||||
|
|
||||
|
my $usage = "unknown argument $cmd, choose one of a:c:d:iadd:idel:ilst:sMAC:?"; |
||||
|
|
||||
|
# get command overview from ahoy-nano device |
||||
|
if($cmd eq "?") |
||||
|
{ |
||||
|
DevIo_SimpleWrite($hash, "$cmd\r\n", 2); |
||||
|
} |
||||
|
elsif($cmd eq "a") |
||||
|
{ |
||||
|
DevIo_SimpleWrite($hash, "a:{$params[1]}:{$params[2]}:{$params[3]}:\r\n", 2); |
||||
|
} |
||||
|
elsif($cmd eq "c") |
||||
|
{ |
||||
|
DevIo_SimpleWrite($hash, "c:{$params[1]}:\r\n", 2); |
||||
|
} |
||||
|
elsif($cmd eq "d") |
||||
|
{ |
||||
|
DevIo_SimpleWrite($hash, "d:{$params[1]}:\r\n", 2); |
||||
|
} |
||||
|
elsif($cmd eq "i") |
||||
|
{ |
||||
|
#todo |
||||
|
#DevIo_SimpleWrite($hash, "off\r\n", 2); |
||||
|
} |
||||
|
elsif($cmd eq "sMAC") |
||||
|
{ |
||||
|
#todo |
||||
|
DevIo_SimpleWrite($hash, "$cmd\r\n", 2); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return $usage; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
# will be executed upon successful connection establishment (see DevIo_OpenDev()) |
||||
|
sub ahoyUL_Init($) |
||||
|
{ |
||||
|
my ($hash) = @_; |
||||
|
|
||||
|
# send init to device, here e.g. enable automode to send DevInfoReq (0x15 ... 0x0B ....) every 120sec and enable simple decoding in ahoy-nano |
||||
|
DevIo_SimpleWrite($hash, "a120:::::d1:\r\n", 2); |
||||
|
|
||||
|
return undef; |
||||
|
} |
||||
|
|
||||
|
1; |
@ -1,151 +0,0 @@ |
|||||
|
|
||||
package main; |
|
||||
|
|
||||
use strict; |
|
||||
use warnings; |
|
||||
use DevIo; # load DevIo.pm if not already loaded |
|
||||
|
|
||||
# called upon loading the module MY_MODULE |
|
||||
sub AHOYUL_Initialize($) |
|
||||
{ |
|
||||
my ($hash) = @_; |
|
||||
|
|
||||
$hash->{DefFn} = "AHOYUL_Define"; |
|
||||
$hash->{UndefFn} = "AHOYUL_Undef"; |
|
||||
$hash->{SetFn} = "AHOYUL_Set"; |
|
||||
$hash->{ReadFn} = "AHOYUL_Read"; |
|
||||
$hash->{ReadyFn} = "AHOYUL_Ready"; |
|
||||
|
|
||||
$hash->{ParseFn} = "AHOYUL_Parse"; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
# called when a new definition is created (by hand or from configuration read on FHEM startup) |
|
||||
sub AHOYUL_Define($$) |
|
||||
{ |
|
||||
my ($hash, $def) = @_; |
|
||||
my @a = split("[ \t]+", $def); |
|
||||
|
|
||||
my $name = $a[0]; |
|
||||
|
|
||||
# $a[1] is always equals the module name "MY_MODULE" |
|
||||
|
|
||||
# first argument is a serial device (e.g. "/dev/ttyUSB0@57600,8,N,1") |
|
||||
my $dev = $a[2]; |
|
||||
|
|
||||
return "no device given" unless($dev); |
|
||||
|
|
||||
# close connection if maybe open (on definition modify) |
|
||||
DevIo_CloseDev($hash) if(DevIo_IsOpen($hash)); |
|
||||
|
|
||||
# add a default baud rate (9600), if not given by user |
|
||||
$dev .= '@57600,8,N,1' if(not $dev =~ m/\@\d+$/); |
|
||||
|
|
||||
# set the device to open |
|
||||
$hash->{DeviceName} = $dev; |
|
||||
|
|
||||
# open connection with custom init function |
|
||||
my $ret = DevIo_OpenDev($hash, 0, "AHOYUL_Init"); |
|
||||
|
|
||||
return undef; |
|
||||
} |
|
||||
|
|
||||
# called when definition is undefined |
|
||||
# (config reload, shutdown or delete of definition) |
|
||||
sub AHOYUL_Undef($$) |
|
||||
{ |
|
||||
my ($hash, $name) = @_; |
|
||||
|
|
||||
# close the connection |
|
||||
DevIo_CloseDev($hash); |
|
||||
|
|
||||
return undef; |
|
||||
} |
|
||||
|
|
||||
# called repeatedly if device disappeared |
|
||||
sub AHOYUL_Ready($) |
|
||||
{ |
|
||||
my ($hash) = @_; |
|
||||
|
|
||||
# try to reopen the connection in case the connection is lost |
|
||||
return DevIo_OpenDev($hash, 1, "AHOYUL_Init"); |
|
||||
} |
|
||||
|
|
||||
# called when data was received |
|
||||
sub AHOYUL_Read($) |
|
||||
{ |
|
||||
my ($hash) = @_; |
|
||||
my $name = $hash->{NAME}; |
|
||||
|
|
||||
# read the available data |
|
||||
my $buf = DevIo_SimpleRead($hash); |
|
||||
|
|
||||
# stop processing if no data is available (device disconnected) |
|
||||
return if(!defined($buf)); |
|
||||
|
|
||||
Log3 $name, 5, "AHOYUL ($name) - received: $buf"; |
|
||||
|
|
||||
# |
|
||||
# do something with $buf, e.g. generate readings, send answers via DevIo_SimpleWrite(), ... |
|
||||
# |
|
||||
|
|
||||
} |
|
||||
|
|
||||
# called if set command is executed |
|
||||
sub AHOYUL_Set($$@) |
|
||||
{ |
|
||||
my ($hash, $name, $params) = @_; |
|
||||
my @a = split("[ \t]+", $params); |
|
||||
$cmd = $params[0] |
|
||||
|
|
||||
my $usage = "unknown argument $cmd, choose one of statusRequest:noArg on:noArg off:noArg"; |
|
||||
|
|
||||
# get command overview from ahoy-nano device |
|
||||
if($cmd eq "?") |
|
||||
{ |
|
||||
#todo |
|
||||
DevIo_SimpleWrite($hash, "?\r\n", 2); |
|
||||
} |
|
||||
elsif($cmd eq "a") |
|
||||
{ |
|
||||
#todo handle automode and send command to ahoy-nano via cmd a[[:<period_sec>]:<12 digit inverter id>:] |
|
||||
DevIo_SimpleWrite($hash, "a:{$params[1]}:{$params[2]}:\r\n", 2); |
|
||||
} |
|
||||
elsif($cmd eq "c") |
|
||||
{ |
|
||||
#todo |
|
||||
#DevIo_SimpleWrite($hash, "off\r\n", 2); |
|
||||
} |
|
||||
elsif($cmd eq "d") |
|
||||
{ |
|
||||
#todo |
|
||||
#DevIo_SimpleWrite($hash, "off\r\n", 2); |
|
||||
} |
|
||||
elsif($cmd eq "i") |
|
||||
{ |
|
||||
#todo |
|
||||
#DevIo_SimpleWrite($hash, "off\r\n", 2); |
|
||||
} |
|
||||
elsif($cmd eq "s") |
|
||||
{ |
|
||||
#todo |
|
||||
#DevIo_SimpleWrite($hash, "off\r\n", 2); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
return $usage; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
# will be executed upon successful connection establishment (see DevIo_OpenDev()) |
|
||||
sub AHOYUL_Init($) |
|
||||
{ |
|
||||
my ($hash) = @_; |
|
||||
|
|
||||
# send init to device, here e.g. enable automode to send DevInfoReq (0x15 ... 0x0B ....) every 120sec and enable simple decoding in ahoy-nano |
|
||||
DevIo_SimpleWrite($hash, "a120:::::d1:\r\n", 2); |
|
||||
|
|
||||
return undef; |
|
||||
} |
|
||||
|
|
||||
1; |
|
@ -0,0 +1,33 @@ |
|||||
|
|
||||
|
TX Ch40 27B | 15 8180595678563412800B 0063492CEE0000000000 000000E21A88 |
||||
|
TX Ch03 27B | 15 8180595678563412800B 0063492D010000000000 00000013C34E |
||||
|
TX Ch61 27B | 15 8180595678563412800B 0063492D110000000000 000000D30E53 |
||||
|
TX Ch23 27B | 15 8180595678563412800B 0063492D990000000000 000000D508DB |
||||
|
TX Ch40 27B | 15 8180595678563412800B 0063492DAD0000000000 000000146E48 |
||||
|
TX Ch61 27B | 15 8180595678563412800B 0063492DBC0000000000 00000044AEC9 |
||||
|
TX Ch03 27B | 15 8180595678563412800B 0063492DCB0000000000 000000B6ED0F |
||||
|
TX Ch23 27B | 15 8180595678563412800B 0063492DE00000000000 00000047073F |
||||
|
TX Ch75 27B | 15 8180595678563412800B 0063492DF00000000000 00000087CA22 |
||||
|
TX Ch23 27B | 15 8180595678563412800B 0063492DFF0000000000 000000778B9C |
||||
|
TX Ch40 27B | 15 8180595678563412800B 0063492E0E0000000000 000000EC720C |
||||
|
TX Ch61 27B | 15 8180595678563412800B 0063492E1D0000000000 000000DCABF6 |
||||
|
TX Ch03 27B | 15 8180595678563412800B 0063492E2D0000000000 000000DDFF93 |
||||
|
TX Ch40 27B | 15 8180595678563412800B 0063492E3C0000000000 0000008D3F12 |
||||
|
|
||||
|
|
||||
|
# test sequence for sending: |
||||
|
smac:ch03:15 8180595678563412800B 0063492CEE0000000000 000000E21A88:rx40: |
||||
|
smac:Ch23:15 8180595678563412800B 0063492D010000000000 00000013C34E:rx61: |
||||
|
smac:Ch40:15 8180595678563412800B 0063492D110000000000 000000D30E53:rx75: |
||||
|
smac:ch61:15 8180595678563412800B 0063492D990000000000 000000D508DB:rx03: |
||||
|
smac:ch75:15 8180595678563412800B 0063492DAD0000000000 000000146E48:rx23: |
||||
|
smac:ch03:15 8180595678563412800B 0063492DBC0000000000 00000044AEC9:rx40: |
||||
|
smac:Ch23:15 8180595678563412800B 0063492DCB0000000000 000000B6ED0F:rx61: |
||||
|
smac:ch40:15 8180595678563412800B 0063492DE00000000000 00000047073F:rx75: |
||||
|
|
||||
|
smac:ch61:15 8180595678563412800B 0063492DF00000000000 00000087CA22:rx03: |
||||
|
smac:ch75:15 8180595678563412800B 0063492DFF0000000000 000000778B9C:rx23: |
||||
|
smac:ch03:15 8180595678563412800B 0063492E0E0000000000 000000EC720C:rx40: |
||||
|
smac:ch23:15 8180595678563412800B 0063492E1D0000000000 000000DCABF6:rx61: |
||||
|
smac:ch40:15 8180595678563412800B 0063492E2D0000000000 000000DDFF93:rx75: |
||||
|
smac:ch63:15 8180595678563412800B 0063492E3C0000000000 0000008D3F12:rx03: |
Loading…
Reference in new issue