# 7-8 solenoid valves + one motorized valve (DC-motor with endswitch)
namespace eval svumot {} {
}

proc stdConfig::svumot {valvelist} {
  controller std "\n" 5

  prop mot 0
  prop startcmd "tv1"
  foreach {name nr} $valvelist {
    if {$nr == 8} {
      # disable button 8 for motor
      prop startcmd "tv0"
    } elseif {$nr eq "mot"} {
      prop mot $name
    } elseif {$nr < 1 || $nr > 9} {
      error "bad valve number / mot: /$nr/"
    }
  }

  obj svumot rd -none
  prop read svumot::read
  prop @closetime 0
  kids "valves" {
    foreach {name nr} $valvelist {
      node $name out
      if {$nr eq "mot"} {
        prop label $name
        prop enum close,open
        prop write svumot::swrite

      } else {
        prop nr $nr
        prop enum 1
        prop write svumot::write
        prop nonewline 1
      }
    }
    node motpos upd
    kids "set" {
      node set out
      default 0
      prop write svumot::wset
    }

    node n2top upd
#    prop visible false
    prop label N2top
    prop newline 1


    node n2bot
    prop label N2bot
  }
}

proc svumot::write {} {
  if {[sct target]} {
    sct send o[sct nr]
  } else {
    sct send c[sct nr]
  }
  [sct controller] queue [sct parent] read read
  return stdSct::completeUpdate
}

proc svumot::swrite {} {
  if {[sct target] == 1 || [sct target] == 3} {
    sct send o9
    sct @closetime -1
  } else {
    sct send c9
    sct @closetime -1
  }
  [sct controller] queue [sct parent] read read
  return stdSct::completeUpdate
}

proc svumot::read {} {
  sct send enmp
  return svumot::update
}

proc svumot::update {} {
  set pos -1
  set state -1
  set error ""
  set valves none
  scan [sct result] "e%d n%f m%f p%f %d %s" state n2a n2b pos valves error
  if {$valves eq "none"} {
    return idle
  }
  updateval [sct]/motpos $pos
  switch $state {
    0 {set enum closed,open}
    1 {set enum close,opened}
    2 {set enum close,open,closing}
    3 {set enum close,open,opening=3}
    7 {set enum unplugged=7}
    default {set enum close,open,$error=$state}
  }
  hsetprop [sct]/[sct mot] enum $enum
  foreach nr {1 2 3 4 5 6 7 8} {
    set vs($nr) 0
  }
  foreach nr [split $valves {}] {
    set vs($nr) 1
  }
  foreach node [hlist [sct]] {
    set nr [silent 0 hgetpropval [sct]/$node nr]
    if {$nr != 0} {
      updateval [sct]/$node $vs($nr)
    }
  }
  updateval [sct]/[sct mot] $state
  if {"$error" ne "" && "$error" ne "stopped"} {
    hsetprop [sct]/motpos geterror $error
  } else {
    hdelprop [sct]/motpos geterror
  }
  updateval [sct]/n2top $n2a
  updateval [sct]/n2bot $n2b
  return idle
}

proc svumot::holdopen {} {
  if {[sct @closetime] < 0} {
    return unpoll
  }
  if {[doubletime] >= [sct @closetime]} {
    sct send s
    return svumot::unpoll
  }
  return idle
}

proc svumot::unpoll {} {
  sct @closetime 0
  [sct controller] queue [sct parent] read read
  return unpoll
}

proc svumot::wset {} {
  if {[sct @closetime] <= 0} {
    set t2o 60
    scan [sct idn] "t%f v" t2o
    set pos [hvali [sct]]
    set posr [hvali [sct parent]]
    if {$pos > $posr + 0.002} {
      set pos [expr $posr + 0.002]
    } elseif {$pos < $posr - 0.002} {
      set pos [expr $posr - 0.002]
    }
    set dif [expr [sct target] - $pos]
    set delta [expr abs($dif) * $t2o]
    if {abs($dif) > 0.0001} {
      sct update [sct target]
      sct @closetime [expr [doubletime] + $delta]
      if {$dif > 0} {
        sct send o9
      } else {
        sct send c9
      }
      [sct controller] poll [sct parent] 0.001 write svumot::holdopen
      return stdSct::complete
    } else {
      sct update $pos
    }
  }
  return idle
}
