From e80c47aa0b7dd0dd0a5430c98cb226776d8d2040 Mon Sep 17 00:00:00 2001 From: golfi200 Date: Wed, 7 Dec 2022 00:13:25 +0100 Subject: [PATCH] simple FHEM collector/parser of arduino decoded message --- .gitignore | 1 + tools/nano/AhoyUL/FHEM/34_ahoyUL.pm | 208 ++++++++++++++++++--------- tools/nano/AhoyUL/src/main.cpp | 13 +- tools/nano/AhoyUL/src/utils_serial.h | 3 +- 4 files changed, 153 insertions(+), 72 deletions(-) diff --git a/.gitignore b/.gitignore index 0f49e032..6bfb10b4 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ tools/esp8266/html/h/* /tools/nano/AhoyUL/myTest_app.py_old.py /tools/nano/AhoyUL/myTest_app.py tools/nano/AhoyUL/FHEM/34_mbStamp02.pm +tools/nano/AhoyUL/FHEM/test.pl diff --git a/tools/nano/AhoyUL/FHEM/34_ahoyUL.pm b/tools/nano/AhoyUL/FHEM/34_ahoyUL.pm index 79be9bd2..b4f9e583 100644 --- a/tools/nano/AhoyUL/FHEM/34_ahoyUL.pm +++ b/tools/nano/AhoyUL/FHEM/34_ahoyUL.pm @@ -5,20 +5,25 @@ 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) = @_; +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); +my $last_hour=0; + +my %sets = ( + "a" => ":[0-9]+:", + "a" => ":[0-9]+:[0-9]{1}:[0-9]{12}:", #automode enable and configure + "c" => "[0-9]+", + "smac" => ":ch[0-9]{2}:[a-fA-F0-9]:rx[0-9]{2}:", #smac command (automode off) + "s" => "", #automode of + "d" => "0,1", #query decoding now + "?" => "", +); + + +my %Inv = { "1141xxxxxxxx", }; +my $yield_day = 0; #todo make per inverter +my $yield_total = 0; + - $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($$) @@ -27,7 +32,6 @@ sub ahoyUL_Define($$) 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") @@ -37,36 +41,71 @@ sub ahoyUL_Define($$) # 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"); - + my $ret = DevIo_OpenDev($hash, 0, "ahoyUL_Init"); + + # start periodic reading + InternalTimer(gettimeofday()+15, "ahoyUL_GetUpdate", $hash); return undef; } -# called when definition is undefined -# (config reload, shutdown or delete of definition) -sub ahoyUL_Undef($$) + + +# will be executed upon successful connection establishment (see DevIo_OpenDev()) +sub ahoyUL_Init($) { - my ($hash, $name) = @_; - - # close the connection - DevIo_CloseDev($hash); + my ($hash) = @_; + my $name = $hash->{NAME}; + Log3 $name, 3, "ahoy device Init() called ..."; + # 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:\nd1\r\n", 2); + + return undef; +} + + + +# 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"; - return undef; + $hash->{ParseFn} = "ahoyUL_Parse"; + $hash->{ParseFn} = "ahoyUL_GetUpdate"; #to be initialized in X_Define with a period + +} + + +sub ahoyUL_GetUpdate($) +{ + my ($hash) = @_; + my $name = $hash->{NAME}; + Log3 $name, 3, "ahoy_GetUpdate called ..."; + + # neuen Timer starten in einem konfigurierten Interval. + #InternalTimer(gettimeofday()+$hash->{cmdInterval}, "ahoyUL_GetUpdate", $hash); + InternalTimer(gettimeofday()+120, "ahoyUL_GetUpdate", $hash); + + #todo: call cmd sender method or do it right here } + # called repeatedly if device disappeared sub ahoyUL_Ready($) { my ($hash) = @_; - + my $name = $hash->{NAME}; + Log3 $name, 3, "ahoyUL_Ready() called ..."; # try to reopen the connection in case the connection is lost return DevIo_OpenDev($hash, 1, "ahoyUL_Init"); } @@ -100,32 +139,67 @@ sub ahoyUL_Read($) # 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 + my ( $hash, $iohash, $name, $rmsg) = @_; + Log3 $name, 3, "ahoyUL: $rmsg"; + $last_hour = $hour; + ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); + if($hour < $last_hour) { + $yield_day = 0; + $yield_total = 0; + readingsSingleUpdate($hash, "yield_dc", "day $yield_day Wh total $yield_total kWh" , 1); + }#end if - } elsif($rmsg =~ m/payload/) { - # payload + if($rmsg =~ m/[rR]{1}MAC/) { + # handle rmac responses + $hash->{RMAC} = $rmsg; + $hash->{RMAC_started} = 1; + $hash->{RMAC_complete} = 0; + + } elsif ($hash->{RMAC_started}) { + $hash->{RMAC} .= $rmsg; + $hash->{RMAC_started} += 1; + if($rmsg =~ m/OK|ERR/) { + #end of rmac detected + $hash->{RMAC_complete} = 1; + $hash->{RMAC} =~ s/\r\n//g; + $hash->{RMAC} .= "\n"; + } elsif ($hash->{RMAC_started} > 10) { + #stop rmac collection insufficiently if OK missed + $hash->{RMAC_started} = 0; + $hash->{RMAC_complete} = 0; + } + + } elsif($rmsg =~ m/payload/) { + # user payload + readingsSingleUpdate($hash, "Payload", $rmsg , 1); - } 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); - } + } elsif($rmsg =~ m/(ch0[0-4])/) { # regex match results to $1 + # decoded message from arduino + readingsSingleUpdate($hash, "dec_$1", $rmsg , 1); + if ($1 eq "ch00") { + #end + readingsSingleUpdate($hash, "yield_dc", "day $yield_day Wh total $yield_total kWh" , 1); + $yield_day = 0; + $yield_total = 0; + } else { + $rmsg =~ m/YieldDay: ([0-9\.]+).*YieldTotal: ([0-9\.]+)/; # regex match results to $1 and $2 + $yield_day += $1; + $yield_total += $2; + } + + } -} + # do further rmac parsing hereafter + if ($hash->{RMAC_complete}) { + readingsSingleUpdate($hash, "MACresp", $hash->{RMAC} , 1); + $hash->{RMAC_started} = 0; + $hash->{RMAC_complete} = 0; + #todo data valid check for OK or ERR + } +}# end X_Parse # called if set command is executed @@ -134,32 +208,33 @@ 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]; + + return "unknown argument $cmd choose one of " . join(" ", sort keys %sets) + if(@params < 2); - my $usage = "unknown argument $cmd, choose one of a:c:d:iadd:idel:ilst:sMAC:?"; + my $usage = "should not come"; # get command overview from ahoy-nano device if($cmd eq "?") { - DevIo_SimpleWrite($hash, "$cmd\r\n", 2); + DevIo_SimpleWrite($hash, "$cmd\n", 2); } elsif($cmd eq "a") { - DevIo_SimpleWrite($hash, "a:{$params[1]}:{$params[2]}:{$params[3]}:\r\n", 2); + DevIo_SimpleWrite($hash, "a:$params[1]:$params[2]:$params[3]:\n", 2); } elsif($cmd eq "c") { - DevIo_SimpleWrite($hash, "c:{$params[1]}:\r\n", 2); + DevIo_SimpleWrite($hash, "c$params[1]:\n", 2); } elsif($cmd eq "d") { - DevIo_SimpleWrite($hash, "d:{$params[1]}:\r\n", 2); + DevIo_SimpleWrite($hash, "d$params[1]:\n", 2); } - elsif($cmd eq "i") + elsif($cmd eq "s") { - #todo - #DevIo_SimpleWrite($hash, "off\r\n", 2); + DevIo_SimpleWrite($hash, "s\n", 2); } elsif($cmd eq "sMAC") { @@ -170,17 +245,18 @@ sub ahoyUL_Set($$@) { return $usage; } + return undef; } - -# 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; +# 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; } 1; \ No newline at end of file diff --git a/tools/nano/AhoyUL/src/main.cpp b/tools/nano/AhoyUL/src/main.cpp index d7a86303..3e02200c 100644 --- a/tools/nano/AhoyUL/src/main.cpp +++ b/tools/nano/AhoyUL/src/main.cpp @@ -83,7 +83,7 @@ static RadioType hmRadio; // static uint64_t radio_id64 = 0ULL; -#define DEF_VERSION "\n version 2022-12-03 11:05" +#define DEF_VERSION "\n version 2022-12-06 21:30" #define P(x) (__FlashStringHelper *)(x) // PROGMEM-Makro for variables static const char COMPILE_DATE[] PROGMEM = {__DATE__}; static const char COMPILE_TIME[] PROGMEM = {__TIME__}; @@ -257,8 +257,8 @@ void loop() { DPRINT(DBG_INFO, F(" ERR")); } //end if-else }//end if(tmp8 > 2)-else - } //end if(tmp8 > 0) + Serial.println(); break; } // end case a @@ -313,6 +313,7 @@ void loop() { }//end if(utSer.uart_cmd_smac_request_parser(...)) } // end if(mac) } // end if(tmp8) + Serial.println(); break; } // end case s @@ -359,6 +360,7 @@ void loop() { // no cmd match } } + Serial.println(); break; } // end case i @@ -378,6 +380,7 @@ void loop() { }//end if }//end while() } + Serial.println(); break; } @@ -412,7 +415,7 @@ void loop() { // cmd:/ "p?" // query power setting //not sure there is a query request - DPRINT(DBG_DEBUG, F("query: not yet, break")); + DPRINTLN(DBG_DEBUG, F("query: not yet, break")); break; } else if (strstr(&mParams[0][0], "%")) { @@ -445,9 +448,9 @@ void loop() { } // end case t case (char)'?':{ - Serial.print(F("\ncmds: a:, c_, d, iadd:, idel:, ilst:, m_, p:, s, smac:, rxch_, t_, ?")); + Serial.println(F("\ncmds: a:, c_, d, iadd:, idel:, ilst:, m_, p:, s, smac:, rxch_, t_, ?")); break; - } //end case '?' + } //end case '?' } // end switch-case } // end if serial... diff --git a/tools/nano/AhoyUL/src/utils_serial.h b/tools/nano/AhoyUL/src/utils_serial.h index 3df2fb34..d70c976d 100644 --- a/tools/nano/AhoyUL/src/utils_serial.h +++ b/tools/nano/AhoyUL/src/utils_serial.h @@ -274,7 +274,7 @@ class SerialUtils { DPRINT(DBG_INFO, _info); _DPRINT(DBG_INFO, _tmp32); } - + Serial.println(); return _tmp32; } // end eval_simple_cmd() @@ -458,6 +458,7 @@ class SerialUtils { } } // end if(strlen(_cmd_params[1])) } // end if(_plen...) + Serial.println(); return _res; } // end uart_inverter_del_check()