###############################################################################
#
# Generic Logic event handlers
#
###############################################################################

#
# This is the namespace in which all functions and variables below will exist.
#
namespace eval Logic {
 
#
# PID process of Smeter measure
#
variable ps_smeter;
global strdtmf;
set strdtmf "";
#
# A variable used to store a timestamp for the last identification.
#
variable prev_ident 0;
 
#
# A constant that indicates the minimum time in seconds to wait between two
# identifications. Manual and long identifications is not affected.
#
variable min_time_between_ident 120;
 
#
# Short and long identification intervals. They are setup from config
# variables below.
#
variable short_ident_interval 0;
variable long_ident_interval 0;
 
 
#
# The ident_only_after_tx variable indicates if identification is only to
# occur after the node has transmitted. The variable is setup below from the
# configuration variable with the same name.
# The need_ident variable indicates if identification is needed.
#
variable ident_only_after_tx 0;
variable need_ident 0;
 
#
# A list of functions that should be called once every whole minute
#
variable timer_tick_subscribers [list];
 
#
# Contains the ID of the last receiver that indicated squelch activity
#
variable sql_rx_id 0;
 
 
#
# Executed when the SvxLink software is started
#
proc startup {} {
 
 
  set ps_smeter [exec python /home/pi/test/smeter.py &]
  playSilence 1000;
  playMsg "SVXCard" "start"

 
  #send_short_ident
}

 
 
 
#
# Executed when a specified module could not be found
#   module_id - The numeric ID of the module
#
proc no_such_module {module_id} {
  playMsg "Core" "no_such_module";
  playNumber $module_id;
}

 
#
# Executed when a manual identification is initiated with the * DTMF code
#
proc manual_identification {} {
  global mycall;
  global report_ctcss;
  global active_module;
  global loaded_modules;
  variable CFG_TYPE;
  variable prev_ident;
 
  set epoch [clock seconds];
  set hour [clock format $epoch -format "%k"];
  regexp {([1-5]?\d)$} [clock format $epoch -format "%M"] -> minute;
  set prev_ident $epoch;
 
  playMsg "Core" "online";
  spellWord $mycall;
  if {$CFG_TYPE == "Repeater"} {
    playMsg "Core" "repeater";
  }
  playSilence 250;
  playMsg "Core" "the_time_is";
  playTime $hour $minute;
  playSilence 250;
  if {$report_ctcss > 0} {
    playMsg "Core" "pl_is";
    playNumber $report_ctcss;
    playMsg "Core" "hz";
    playSilence 300;
  }
  if {$active_module != ""} {
    playMsg "Core" "active_module";
    playMsg $active_module "name";
    playSilence 250;
    set func "::";
    append func $active_module "::status_report";
    if {"[info procs $func]" ne ""} {
      $func;
    }
  } else {
    foreach module [split $loaded_modules " "] {
      set func "::";
      append func $module "::status_report";
      if {"[info procs $func]" ne ""} {
        $func;
      }
    }
  }
  playMsg "Default" "press_0_for_help"
  playSilence 250;
}

 
#
# Executed when a short identification should be sent
#   hour    - The hour on which this identification occur
#   minute  - The hour on which this identification occur
#
proc send_short_ident {{hour -1} {minute -1}} {
  global mycall;
  variable CFG_TYPE;
 
  spellWord $mycall;
  if {$CFG_TYPE == "Repeater"} {
    playMsg "Core" "repeater";
  }
  playSilence 500;
}

 
#
# Executed when a long identification (e.g. hourly) should be sent
#   hour    - The hour on which this identification occur
#   minute  - The hour on which this identification occur
#
proc send_long_ident {hour minute} {
  global mycall;
  global loaded_modules;
  global active_module;
  variable CFG_TYPE;
 
  spellWord $mycall;
  if {$CFG_TYPE == "Repeater"} {
    playMsg "Core" "repeater";
  }
  playSilence 500;
 
  playMsg "Core" "the_time_is";
  playSilence 100;
  playTime $hour $minute;
  playSilence 500;
 
    # Call the "status_report" function in all modules if no module is active
  if {$active_module == ""} {
    foreach module [split $loaded_modules " "] {
      set func "::";
      append func $module "::status_report";
      if {"[info procs $func]" ne ""} {
        $func;
      }
    }
  }
 
  playSilence 500;
}

 
#
# Executed when the squelch just have closed and the RGR_SOUND_DELAY timer has
# expired.
#
proc send_rgr_sound {} {
  variable sql_rx_id;
 
#lecture du signal
  source "/etc/svxlink/smeter/smeter.tcl"
  puts "signal roger beep  $signal";
  set son ""
  if {$signal >=0} {
 
        #playMsg "TclSSTV" "signal";
        #playNumber  $signal
        if {$signal>=10} {
                set son "s9plus" ; } else {
                append son "s" $signal ;
        }
 
        playMsg "Smeter" $son;
  }
 
 
CW::setCpm 90;
CW::setPitch 890;
CW::setAmplitude 350;
CW::play "k"

#  playTone 440 500 100;
#  playSilence 200;
 
# for {set i 0} {$i < $sql_rx_id} {incr i 1} {
#    playTone 880 500 50;
#    playSilence 50;
#  }
  playSilence 100;
}

 
#
# Executed when an empty macro command (i.e. D#) has been entered.
#
proc macro_empty {} {
  playMsg "Core" "operation_failed";
}

 
#
# Executed when an entered macro command could not be found
#
proc macro_not_found {} {
  playMsg "Core" "operation_failed";
}

 
#
# Executed when a macro syntax error occurs (configuration error).
#
proc macro_syntax_error {} {
  playMsg "Core" "operation_failed";
}

 
#
# Executed when the specified module in a macro command is not found
# (configuration error).
#
proc macro_module_not_found {} {
  playMsg "Core" "operation_failed";
}

 
#
# Executed when the activation of the module specified in the macro command
# failed.
#
proc macro_module_activation_failed {} {
  playMsg "Core" "operation_failed";
}

 
#
# Executed when a macro command is executed that requires a module to
# be activated but another module is already active.
#
proc macro_another_active_module {} {
  global active_module;
 
  playMsg "Core" "operation_failed";
  playMsg "Core" "active_module";
  playMsg $active_module "name";
}

 
#
# Executed when an unknown DTMF command is entered
#   cmd - The command string
#
proc unknown_command {cmd} {
  spellWord $cmd;
  playMsg "Core" "unknown_command";
}

 
#
# Executed when an entered DTMF command failed
#   cmd - The command string
#
proc command_failed {cmd} {
  spellWord $cmd;
  playMsg "Core" "operation_failed";
}

 
#
# Executed when a link to another logic core is activated.
#   name  - The name of the link
#
proc activating_link {name} {
  if {[string length $name] > 0} {
    playMsg "Core" "activating_link_to";
    spellWord $name;
  }
}

 
#
# Executed when a link to another logic core is deactivated.
#   name  - The name of the link
#
proc deactivating_link {name} {
  if {[string length $name] > 0} {
    playMsg "Core" "deactivating_link_to";
    spellWord $name;
  }
}

 
#
# Executed when trying to deactivate a link to another logic core but the
# link is not currently active.
#   name  - The name of the link
#
proc link_not_active {name} {
  if {[string length $name] > 0} {
    playMsg "Core" "link_not_active_to";
    spellWord $name;
  }
}

 
#
# Executed when trying to activate a link to another logic core but the
# link is already active.
#   name  - The name of the link
#
proc link_already_active {name} {
  if {[string length $name] > 0} {
    playMsg "Core" "link_already_active_to";
    spellWord $name;
  }
}

 
#
# Executed each time the transmitter is turned on or off
#   is_on - Set to 1 if the transmitter is on or 0 if it's off
#
proc transmit {is_on} {
  #puts "Turning the transmitter $is_on";
  variable prev_ident;
  variable need_ident;
  if {$is_on && ([clock seconds] - $prev_ident > 5)} {
    set need_ident 1;
  }
}

 
#
# Executed each time the squelch is opened or closed
#   rx_id   - The ID of the RX that the squelch opened/closed on
#   is_open - Set to 1 if the squelch is open or 0 if it's closed
#
proc squelch_open {rx_id is_open} {
  variable sql_rx_id;
### Added for Smeter
  variable ps_smeter;
#  variable signal_smeter;
### Added for Smeter

  #puts "The squelch is $is_open on RX $rx_id";
  set sql_rx_id $rx_id;
 
 ### Starting/Stopping Smeter for SVXCard
 if {$is_open } {
  #start the signal measuring
 # set ps_smeter [exec python /home/pi/test/smeter.py &];
 # puts "ps_smeter = $ps_smeter"
 }
#  else {
#puts "  Au kill, ps_smeter = $ps_smeter"
   # stop the signal measuring
#   set runcmd [exec sleep 1 ; kill -0 $ps_smeter &];
# }
 
}

 
#
# Executed when a DTMF digit has been received
#   digit     - The detected DTMF digit
#   duration  - The duration, in milliseconds, of the digit
#
# Return 1 to hide the digit from further processing in SvxLink or
# return 0 to make SvxLink continue processing as normal.
#
proc dtmf_digit_received {digit duration} {
variable strdtmf;
 #  puts "DTMF digit \"$digit\" detected with duration $duration ms";
 
#when DTMF is coming truth a echo command, the durations are always 100ms.
# events can by trigger by
# 1- launch svxlink by this command :    nc -lk 10000 | sudo svxlink
# 2- give interruption command via DTMF long string code with : echo 212654321### | nc 127.0.0.1 10000
# the point 2 can by done via a network - replacing 127.0.0.1 by the distant ip of svxlink
 if {$duration==100 } {
 #concatenation with global variable (declaration in namespace)
  append strdtmf  $digit;
  # value to find in the code. If find, execute a command ou playing a wav sound. Reset the memory string
  if { [string first 654321# $strdtmf 0 ] != -1   } {
  spellWord "OK.";
  set strdtmf ""
 }
}
  return 0;
}

 
#
# Executed when a DTMF command has been received
#   cmd - The command
#
# Return 1 to hide the command from further processing is SvxLink or
# return 0 to make SvxLink continue processing as normal.
#
# This function can be used to implement your own custom commands or to disable
# DTMF commands that you do not want users to execute.
proc dtmf_cmd_received {cmd} {
  #global active_module

  # Example: Ignore all commands starting with 3 in the EchoLink module
  #if {$active_module == "EchoLink"} {
  #  if {[string index $cmd 0] == "3"} {
  #    puts "Ignoring random connect command for module EchoLink: $cmd"
  #    return 1
  #  }
  #}

  # Handle the "force core command" mode where a command is forced to be
  # executed by the core command processor instead of by an active module.
  # The "force core command" mode is entered by prefixing a command by a star.
  #if {$active_module != "" && [string index $cmd 0] != "*"} {
  #  return 0
  #}
  #if {[string index $cmd 0] == "*"} {
  #  set cmd [string range $cmd 1 end]
  #}
 
  puts "DTMF décodé $cmd"
  # Example: Custom command executed when DTMF 99 is received
  if {$cmd == "99"} {
    puts "Executing external command 99"
    #playMsg "Core" "online"
    #set runcmd [exec ls &]
    #set runcmd [exec python /usr/share/svxlink/events.d/local/temperature.py > /usr/share/svxlink/events.d/local/temperature.tcl]
 set runcmd [exec python /usr/share/svxlink/events.d/local/temperature.py 2>&1]
 spellWord $runcmd
 #    source "/usr/share/svxlink/events.d/local/temperature.tcl"
 #   puts "temperature = $temperature";
    playMsg "SVXCard" "temperature"
    playNumber  $runcmd
    playMsg "SVXCard" "degrees"
    puts $runcmd
    return 1
  }
 
  if {$cmd == "886788977576"} {
    spellWord "OK"
    return 1
  }
 
  return 0
}

 
#
# Executed once every whole minute. Don't put any code here directly
# Create a new function and add it to the timer tick subscriber list
# by using the function addTimerTickSubscriber.
#
proc every_minute {} {
  variable timer_tick_subscribers;
  puts [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S"];
  foreach subscriber $timer_tick_subscribers {
    $subscriber;
  }
}

 
#
# Use this function to add a function to the list of functions that
# should be executed once every whole minute. This is not an event
# function but rather a management function.
#
proc addTimerTickSubscriber {func} {
  variable timer_tick_subscribers;
  lappend timer_tick_subscribers $func;
}

 
#
# Should be executed once every whole minute to check if it is time to
# identify. Not exactly an event function. This function handle the
# identification logic and call the send_short_ident or send_long_ident
# functions when it is time to identify.
#
proc checkPeriodicIdentify {} {
  variable prev_ident;
  variable short_ident_interval;
  variable long_ident_interval;
  variable min_time_between_ident;
  variable ident_only_after_tx;
  variable need_ident;
  global logic_name;
 
  if {$short_ident_interval == 0} {
    return;
  }
 
  set now [clock seconds];
  set hour [clock format $now -format "%k"];
  regexp {([1-5]?\d)$} [clock format $now -format "%M"] -> minute;
 
  set short_ident_now \
            [expr {($hour * 60 + $minute) % $short_ident_interval == 0}];
  set long_ident_now 0;
  if {$long_ident_interval != 0} {
    set long_ident_now \
            [expr {($hour * 60 + $minute) % $long_ident_interval == 0}];
  }
 
  if {$long_ident_now} {
    puts "$logic_name: Sending long identification...";
    send_long_ident $hour $minute;
    set prev_ident $now;
    set need_ident 0;
  } else {
    if {$now - $prev_ident < $min_time_between_ident} {
      return;
    }
    if {$ident_only_after_tx && !$need_ident} {
      return;
    }
 
    if {$short_ident_now} {
      puts "$logic_name: Sending short identification...";
      send_short_ident $hour $minute;
      set prev_ident $now;
      set need_ident 0;
    }
  }
}

 
#
# Executed when the QSO recorder is being activated
#
proc activating_qso_recorder {} {
  playMsg "Core" "activating";
  playMsg "Core" "qso_recorder";
}

 
#
# Executed when the QSO recorder is being deactivated
#
proc deactivating_qso_recorder {} {
  playMsg "Core" "deactivating";
  playMsg "Core" "qso_recorder";
}

 
#
# Executed when trying to deactivate the QSO recorder even though it's
# not active
#
proc qso_recorder_not_active {} {
  playMsg "Core" "qso_recorder";
  playMsg "Core" "not_active";
}

 
#
# Executed when trying to activate the QSO recorder even though it's
# already active
#
proc qso_recorder_already_active {} {
  playMsg "Core" "qso_recorder";
  playMsg "Core" "already_active";
}

 
#
# Executed when the timeout kicks in to activate the QSO recorder
#
proc qso_recorder_timeout_activate {} {
  playMsg "Core" "timeout"
  playMsg "Core" "activating";
  playMsg "Core" "qso_recorder";
}

 
#
# Executed when the timeout kicks in to deactivate the QSO recorder
#
proc qso_recorder_timeout_deactivate {} {
  playMsg "Core" "timeout"
  playMsg "Core" "deactivating";
  playMsg "Core" "qso_recorder";
}

 
#
# Executed when the user is requesting a language change
#
proc set_language {lang_code} {
  global logic_name;
  puts "$logic_name: Setting language $lang_code (NOT IMPLEMENTED)";
 
}

 
#
# Executed when the user requests a list of available languages
#
proc list_languages {} {
  global logic_name;
  puts "$logic_name: Available languages: (NOT IMPLEMENTED)";
 
}

 
#
# Executed when the node is being brought online or offline
#
proc logic_online {online} {
  global mycall
  variable CFG_TYPE
 
  if {$online} {
    playMsg "Core" "online";
    spellWord $mycall;
    if {$CFG_TYPE == "Repeater"} {
      playMsg "Core" "repeater";
    }
  }
}

 
##############################################################################
#
# Main program
#
##############################################################################
 
if [info exists CFG_SHORT_IDENT_INTERVAL] {
  if {$CFG_SHORT_IDENT_INTERVAL > 0} {
    set short_ident_interval $CFG_SHORT_IDENT_INTERVAL;
  }
}
 
if [info exists CFG_LONG_IDENT_INTERVAL] {
  if {$CFG_LONG_IDENT_INTERVAL > 0} {
    set long_ident_interval $CFG_LONG_IDENT_INTERVAL;
    if {$short_ident_interval == 0} {
      set short_ident_interval $long_ident_interval;
    }
  }
}
 
if [info exists CFG_IDENT_ONLY_AFTER_TX] {
  if {$CFG_IDENT_ONLY_AFTER_TX > 0} {
    set ident_only_after_tx $CFG_IDENT_ONLY_AFTER_TX;
  }
}

 
 
# end of namespace
}

#
# This file has not been truncated
#