namespace eval motorvalve {
}

proc stdConfig::motorvalve {} {
  variable name

  controller syncedprot
  prop write stdSct::complete
  pollperiod 1 1

  obj MotorValve -int wr
  prop enum closed,closing,opening,opened,undefined
  prop check motorvalve::check_valve
  prop write motorvalve::set_valve
  prop read motorvalve::get_valve
  prop buttontitle "operate valve"
  prop buttons open/2/2,3:close/1/0,1
  prop mot ${name}_mot
  prop try 0

  kids "$name motor valve" {
  } 
}

proc motorvalve::set_valve_status {new} {
  set old [silent "" sct valvestatus]
  set path [sct objectPath]/status
  set status [hvali $path]
  if {$new ne "" || $old eq $status} {
    hupdate $path $new
  }
  sct valvestatus $new
}

proc motorvalve::check_valve {} {
  set_valve_status ""
  sct try 5
  sct slowspeed 50
}

proc motorvalve::set_valve {} {
  set val [hvali [sct]]
  if {[sct target] < 2} {
    if {[hvali [sct]/[sct mot]/encoder] > 20} {
      [sct mot] maxspeed 200
      sctsync {
        run [sct mot] 15
      }
    }
    set val 1
    sct update 1
    return motorvalve::slow_close
  } elseif {[sct target] < 4} {
    [sct mot] maxspeed 200
    hset [sct]/[sct mot] [hval [sct]/[sct mot]/upperlimit]
    set val 2
  }
  sct update $val
  return idle
}

proc motorvalve::slow_close {} {
  [sct mot] maxspeed [sct slowspeed]
  sct slowspeed [expr max(10,[sct slowspeed] - 10)]
  run [sct mot] [hval [sct]/[sct mot]/lowerlimit]
  return idle
}

proc motorvalve::get_valve {} {
  set p [sct]/[sct mot]
  set stat [hgetpropval $p status]
  set pos [hvali $p/encoder]
  if {$pos < [hval $p/lowerlimit] - 15 ||
      $pos > [hval $p/upperlimit] + 15} {
    hsetprop $p/encoder adjust_zero 1
    return idle
  }
  set dir [string map {0 close 1 close 2 open 3 open 4 undefined} [silent 4 sct target]]
  if {[sct try] == 0} {
    set dir undefined
  }
  if {$stat eq "run"} {
    if {[hgetpropval $p target] > $pos} {
      sct update 2
    } else {
      sct update 1
    }
  } elseif {$pos < 2 && $dir ne "open"} {
    sct update 0 ;# closed
    sct try 0
    set_valve_status ""
  } elseif {$pos > 30 && $dir ne "close"} {
    sct update 3 ;# opened
    sct try 0
    set_valve_status ""
  } else {
    if {[sct try] > 1 && $dir ne "undefined"} {
      set try [sct try]
      incr try -1
      if {$try <= 3} {
        clientput "[sct] try again to $dir ($try)"
      }
      hset [sct] [sct target]
      sct try $try
    } else {
      sct try 0
      if {$dir ne "undefined"} {
        set txt "cannot $dir valve at He pump. Please do it manually"
        clientput "ERROR: $txt"
        set_valve_status $txt
        sct target 4
      }
      sct update 4 ;# undefined
    }
  }
  return idle
}

