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