From c86a914be0d3029a361dc813074ab6a4a6dea099 Mon Sep 17 00:00:00 2001 From: viegener Date: Sun, 26 Feb 2017 12:53:23 +0000 Subject: [PATCH] 42_Nextion: attributes disable/timeout, fix for page 10 git-svn-id: https://svn.fhem.de/fhem/trunk@13529 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/42_Nextion.pm | 191 +++++++++++++++++++++++++++------------- 2 files changed, 133 insertions(+), 59 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 96c1a5e40..483a4d0e8 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 42_Nextion: attributes disable/timeout, fix for page 10 - update: 02_FTUISRV: doc change on ftui-if - feature: 50_TelegramBot: Secured: api key handled in setkey/getkey msgChatId with peer / communication with TBot_List diff --git a/fhem/FHEM/42_Nextion.pm b/fhem/FHEM/42_Nextion.pm index 8eede6e35..9d3e9194c 100644 --- a/fhem/FHEM/42_Nextion.pm +++ b/fhem/FHEM/42_Nextion.pm @@ -52,19 +52,21 @@ # 0.5 2016-06-30 disconnect-fix / log reduced / expectAnswer # # 0.6 2016-10-29 available through SVN +# +# Implement attributes "disable" and "timeout" +# reduced logging for cmd send +# fix for page 10 not recognized : #msg592948 +# 0.7 2017-02-26 disable/timeout, fix for page 10 + +# +# # ############################################## ############################################## ### TODO # -# Tutorial # react on events with commands allowing values from FHEM # remove wait for answer by attribute -# commands -# set - page x -# set - text elem text -# set - val elem val -# picture setting # init page from fhem might sent a magic starter and finisher something like get 4711 to recognize the init command results (can be filtered away) # number of pages as define (std max 0-9) # add 0x65 code @@ -151,7 +153,7 @@ Nextion_Initialize($) $hash->{AttrFn} = "Nextion_Attr"; $hash->{AttrList} = "initPage0:textField-long initPage1:textField-long initPage2:textField-long initPage3:textField-long initPage4:textField-long ". "initPage5:textField-long initPage6:textField-long initPage7:textField-long initPage8:textField-long initPage9:textField-long ". - "initCommands:textField-long hasSendMe:0,1 expectAnswer:1,0 ".$readingFnAttributes; + "initCommands:textField-long hasSendMe:0,1 expectAnswer:1,0 disable:0,1 timeout ".$readingFnAttributes; # Normal devices $hash->{DefFn} = "Nextion_Define"; @@ -180,7 +182,7 @@ Nextion_Define($$) $hash->{DeviceName} = $dev; return undef if($dev eq "none"); # DEBUGGING - my $ret = DevIo_OpenDev($hash, 0, "Nextion_DoInit"); + my $ret = Nextion_Connect($hash); return $ret; } @@ -266,9 +268,9 @@ sub Nextion_Attr(@) { return "\"Nextion_Attr: \" $name does not exist" if (!defined($hash)); if (defined($aVal)) { - Log3 $name, 5, "Nextion_Attr $name: $cmd on $aName to $aVal"; + Log3 $name, 5, "Nextion_Attr $name: $cmd on $aName to $aVal"; } else { - Log3 $name, 5, "Nextion_Attr $name: $cmd on $aName to "; + Log3 $name, 5, "Nextion_Attr $name: $cmd on $aName to "; } # $cmd can be "del" or "set" # $name is device name @@ -282,43 +284,104 @@ sub Nextion_Attr(@) { if ( $aVal !~ /^[[:digit:]]+$/ ) { return "\"Nextion_Attr: \" unsupported"; } + } elsif ($aName eq 'timeout') { + return "Usage: attr $name $aName " if($aVal && $aVal !~ m/^[0-9]{1,6}(,[0-9]{1,6})*/); + RemoveInternalTimer($hash, "Nextion_CheckAlive"); + if($aVal) { + InternalTimer(gettimeofday()+$aVal, "Nextion_CheckAlive", $hash, 0); + if ($aVal >= 10){ + $hash->{nextOpenDelay} = $aVal - 3; + } else { + $hash->{nextOpenDelay} = 10; + } + } + } elsif ($aName eq "disable") { + if (defined($aVal) && $aVal eq "1") { + DevIo_CloseDev($hash); + delete $hash->{DevIoJustClosed} if($hash->{DevIoJustClosed}); + readingsSingleUpdate($hash, 'state', 'disabled', 0); + } else { + readingsSingleUpdate($hash, "state", "disconnected", 0) if($hash->{STATE} eq "disabled"); + InternalTimer(gettimeofday()+1, "Nextion_DoInit", $hash); + } } - $_[3] = $aVal; } + if ($cmd eq "del") { + if ($aName eq 'timeout') { + RemoveInternalTimer($hash, "Nextion_CheckAlive"); + delete ($hash->{nextOpenDelay}); + } + } return undef; } - - - ##################################### sub -Nextion_DoInit($) -{ - my $hash = shift; +Nextion_DoInit($){ + my ($hash) = @_; my $name = $hash->{NAME}; my $ret = undef; - - ### send init commands - my $initCmds = AttrVal( $name, "initCommands", undef ); + + RemoveInternalTimer($hash, "Nextion_CheckAlive"); + if(!IsDisabled($name)) { + InternalTimer(gettimeofday() +3, "Nextion_CheckAlive", $hash, 0); + ### send init commands + my $initCmds = AttrVal( $name, "initCommands", undef ); - Log3 $name, 3, "Nextion_DoInit $name: Execute initCommands :".(defined($initCmds)?$initCmds:"").":"; + Log3 $name, 3, "Nextion_DoInit $name: Execute initCommands :".(defined($initCmds)?$initCmds:"").":"; - - ## ??? quick hack send on init always page 0 twice to ensure proper start - # Send command handles replaceSetMagic and splitting - $ret = Nextion_SendCommand( $hash, "page 0;page 0", 0 ); - - # Send command handles replaceSetMagic and splitting - $ret = Nextion_SendCommand( $hash, $initCmds, 0 ) if ( defined( $initCmds ) ); + ## ??? quick hack send on init always page 0 twice to ensure proper start + # Send command handles replaceSetMagic and splitting + $ret = Nextion_SendCommand( $hash, "page 0;page 0", 0 ); + # Send command handles replaceSetMagic and splitting + $ret = Nextion_SendCommand( $hash, $initCmds, 0 ) if ( defined( $initCmds ) ); + } else { + readingsSingleUpdate($hash, "state", "disabled", 1); + } return $ret; } +##################################### +sub +Nextion_CheckAlive(){ + my ($hash) = @_; + my $name = $hash->{NAME}; + + RemoveInternalTimer($hash, "Nextion_CheckAlive"); + my $attrVal = AttrVal($name, "timeout", undef); + if(defined($attrVal)) { + InternalTimer(gettimeofday() + $attrVal, "Nextion_CheckAlive", $hash, 0); + if(AttrVal($name, "disable", "0") != "1") { + my $ret; + Log3 $name, 5, "Nextion check now if Nextion is alive."; + my $msg = "get \"ping\""; + $ret = Nextion_SendCommand( $hash, $msg, 1 ); + if ($ret ne "Message received"){ + readingsSingleUpdate($hash, "state", "disconnected", 1) if($hash->{STATE} ne "disconnected"); + DevIo_Disconnected($hash) if($hash->{STATE} ne "disconnected"); + } + } + } + return DevIo_OpenDev($hash, 1, "Nextion_DoInit") if($hash->{STATE} eq "disconnected"); +} +###################################### +sub Nextion_Connect($;$) { + my ($hash, $mode) = @_; + my $name = $hash->{NAME}; + + $mode = 0 if!($mode); + if(!IsDisabled($name)) { + my $ret = undef; + $ret = DevIo_OpenDev($hash, 1, "Nextion_DoInit") if($hash->{STATE} eq "disconnected"); + return $ret; + } + return undef; +} ##################################### sub Nextion_Undef($@) @@ -348,7 +411,7 @@ Nextion_SendCommand($$$) my $name = $hash->{NAME}; my @ret; - Log3 $name, 1, "Nextion_SendCommand $name: send commands :".$msg.": "; + Log3 $name, 4, "Nextion_SendCommand $name: send commands :".$msg.": "; # First replace any magics my %dummy; @@ -391,7 +454,7 @@ Nextion_SendSingleCommand($$$) my ($hash,$msg,$answer) = @_; my $name = $hash->{NAME}; - $answer = 0 if ( ! AttrVal($name,"expectAnswer",0) ); + $answer = 0 if ( ! AttrVal($name,"expectAnswer",0) and $answer != 1); # ??? handle answer my $err; @@ -408,12 +471,13 @@ Nextion_SendSingleCommand($$$) Log3 $name, 1, "Nextion_SendCommand Error :".$err.": " if ( defined($err) ); Log3 $name, 4, "Nextion_SendCommand Success " if ( ! defined($err) ); - # Also set sentMsg Id and result in Readings + # Also set sentMsg Id and result in Readings + if ($msg ne "get \"ping\""){ readingsBeginUpdate($hash); readingsBulkUpdate($hash, "cmdSent", $msg); readingsBulkUpdate($hash, "cmdResult", (( defined($err))?$err:"empty") ); readingsEndUpdate($hash, 1); - + } return $err; } @@ -460,35 +524,35 @@ Nextion_Read($@) } Log3 $name, 4, "Nextion: Received message :$msg:"; - - if ( defined( ReadingsVal($name,"received",undef) ) ) { - if ( defined( ReadingsVal($name,"old1",undef) ) ) { - if ( defined( ReadingsVal($name,"old2",undef) ) ) { - if ( defined( ReadingsVal($name,"old3",undef) ) ) { - if ( defined( ReadingsVal($name,"old4",undef) ) ) { - $hash->{READINGS}{old5}{VAL} = $hash->{READINGS}{old4}{VAL}; - $hash->{READINGS}{old5}{TIME} = $hash->{READINGS}{old4}{TIME}; + # Ignore CheckAlive ping + if ($msg ne "H70(p) H70(p) H69(i) H6e(n) H67(g)") { + if ( defined( ReadingsVal($name,"received",undef) ) ) { + if ( defined( ReadingsVal($name,"old1",undef) ) ) { + if ( defined( ReadingsVal($name,"old2",undef) ) ) { + if ( defined( ReadingsVal($name,"old3",undef) ) ) { + if ( defined( ReadingsVal($name,"old4",undef) ) ) { + $hash->{READINGS}{old5}{VAL} = $hash->{READINGS}{old4}{VAL}; + $hash->{READINGS}{old5}{TIME} = $hash->{READINGS}{old4}{TIME}; + } + $hash->{READINGS}{old4}{VAL} = $hash->{READINGS}{old3}{VAL}; + $hash->{READINGS}{old4}{TIME} = $hash->{READINGS}{old3}{TIME}; } - $hash->{READINGS}{old4}{VAL} = $hash->{READINGS}{old3}{VAL}; - $hash->{READINGS}{old4}{TIME} = $hash->{READINGS}{old3}{TIME}; + $hash->{READINGS}{old3}{VAL} = $hash->{READINGS}{old2}{VAL}; + $hash->{READINGS}{old3}{TIME} = $hash->{READINGS}{old2}{TIME}; } - $hash->{READINGS}{old3}{VAL} = $hash->{READINGS}{old2}{VAL}; - $hash->{READINGS}{old3}{TIME} = $hash->{READINGS}{old2}{TIME}; + $hash->{READINGS}{old2}{VAL} = $hash->{READINGS}{old1}{VAL}; + $hash->{READINGS}{old2}{TIME} = $hash->{READINGS}{old1}{TIME}; } - $hash->{READINGS}{old2}{VAL} = $hash->{READINGS}{old1}{VAL}; - $hash->{READINGS}{old2}{TIME} = $hash->{READINGS}{old1}{TIME}; + $hash->{READINGS}{old1}{VAL} = $hash->{READINGS}{received}{VAL}; + $hash->{READINGS}{old1}{TIME} = $hash->{READINGS}{received}{TIME}; } - $hash->{READINGS}{old1}{VAL} = $hash->{READINGS}{received}{VAL}; - $hash->{READINGS}{old1}{TIME} = $hash->{READINGS}{received}{TIME}; - } - - readingsBeginUpdate($hash); - readingsBulkUpdate($hash,"received",$msg); - readingsBulkUpdate($hash,"rectext",( (defined($text)) ? $text : "" )); - readingsBulkUpdate($hash,"currentPage",$id) if ( ( defined( $id ) ) && ( AttrVal($name,"hasSendMe",0) ) ); - - readingsEndUpdate($hash, 1); + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"received",$msg); + readingsBulkUpdate($hash,"rectext",( (defined($text)) ? $text : "" )); + readingsBulkUpdate($hash,"currentPage",$id) if ( ( defined( $id ) ) && ( AttrVal($name,"hasSendMe",0) ) ); + readingsEndUpdate($hash, 1); + } } } else { last; @@ -582,9 +646,10 @@ sub Nextion_Ready($) { my ($hash) = @_; + my $name = $hash->{NAME}; + + Nextion_Connect($hash, 1); - return DevIo_OpenDev($hash, 1, "Nextion_DoInit") - if($hash->{STATE} eq "disconnected"); return 0; } @@ -666,7 +731,8 @@ Nextion_convertMsg($) $text .= $rest; $val = $rest; } - } elsif ( $raw =~ /^\x66(.)$/ ) { + } elsif ( $raw =~ /^\x66(.)$/s ) { + # need to parse multiline due to issue with page 10 --> x0A # page started $text = "page "; my $rest = $1; @@ -800,6 +866,13 @@ Nextion_DecodeFromIso($)
  • expectAnswer <1 or 0>
    Specify if an answer from display is expected. If set to zero no answer is expected at any time on a command.
  • +
  • disable <1 or 0>
    + 0 = The device is enabled | 1 = The device is deactivated. +
  • + +
  • timeout
    + Asks the Nextion every timeout seconds if it is still alive. If there is no response it reconnects to the Nextion.
    +