# CCU 4
namespace eval ccu4_6 {} {
  variable deviceaction 1
  variable newdevice ""
}

proc stdConfig::ccu4_6 {} {
  variable name
  variable node
  
  controller std "\n" 5
  prop startcmd "cid csf"
  hsetprop $node/tasks complete ccu4_6::completeStart
  prop write ccu4_6::write
  prop commerror ccu4_6::errorScript
  prop obj /$name
  
  pollperiod 0.5 0.5
  obj ccu4_6 rd -int
  prop enum 1
  prop label on
  prop read ccu4_6::read
  prop cfgtablefile ccu4.cfgtable
  prop layoutpos 99
  default 1
  kids CCU4 {
    node autodevice par -int 1
    prop enum 1
    
    node f upd
    prop label flow
    
    node fav out -int
    prop enum 1
    prop label "flow available"
  
    node fs out -int
    prop enum ok,no_sens
  
    node fm upd -int
    prop enum idle,opening,closing,opened,closed,no_motor
  
    node fa out -int
    prop enum fixed,controlled,automatic
    
    node mav out -int
    prop enum 1
    prop label "n.v. motor available"
  
    node mp out
    prop label "motor pulse"
  
    node mc out
    prop label "motor current"
  
    node mfc out
    prop label "free current"
  
    node moc out
    prop label "overrun const"
  
    node mtc out
    prop label "torque const"
  
    node mtl upd
    prop label "torque limit"
  
    node mft out
    prop label "flow target"
  
    node mt upd
    prop label "torque"
  
    node mo upd
    prop label "overrun"
  
    node mcr upd
    prop label "read current"

    node mot upd
    prop label "open time"

    node mw out
    prop label "wiggle"

    node h upd
    prop label "he level"
    
    node hr upd
    prop label "he sensor mm"
    
    node hav out
    prop enum 1
    prop label "He lev. available"
  
    node hc upd
    prop label "He meas. current"
    
    node hu upd
    prop label "He meas. volt"
    
    node hh out
    prop label "He full level"
    
    node hl out
    prop label "He fill level"
    
    node htf out
    prop label "fast period"
    prop help "meas. period in fast mode"
    
    node hts out
    prop label "slow period"
    prop help "meas. period in slow mode"
    
    node hd out
    prop label "He driv. current"
    
    node hwr out
    prop label "He wire res."
    
    node hem out
    prop label "empty"
    prop help "sensor length in mm from top to empty pos."
    
    node hfu out
    prop label "full"
    prop help "sensor length in mm from top to full pos."
    
    node hcd out -int
    prop enum stop,fill,off,auto
        
    node hv upd -int
    prop enum fill_valve_off,filling,no_fill_valve,timeout,timeout1
    
    node hsf upd -int
    prop enum sens_ok,sens_warm,no_sens,timeout,not_yet_read,disabled
    
    node ha out -int
    prop enum 1
    prop label "He auto fill"
    
    node hm upd -int
    prop enum 1
    prop label measure
    
    node hf out -int
    prop enum slow,fast
    
    node hbe out -int
    prop enum 1
    prop label LHe 48V enabled
    
    node hmf upd
    prop label "meas first"
    
    node hms upd
    prop label "meas speed"

    node hit out
    prop label "increase tolerance"

    node hft out -int
    prop label "fast/fill timeout"
    
    node hea out
    prop label "add. He channels"

    node hch out -int
    prop label "LHe channel"  
  
    for {set ch 0} {$ch < 6} {incr ch} {
      node h$ch upd
      prop errvar hs$ch
      prop newline 1

      node hs$ch upd -int
      prop enum sens_ok,sens_warm,no_sens,timeout,not_yet_read,disabled
      prop nonewline 1

    }

    node nav out -int
    prop newline 1
    prop enum 1
    prop label "N2 available"
    
    node nu upd
    prop label "N2 upper"
    
    node nl upd
    prop label "N2 lower"
    
    node nth out
    prop label "N2 threshold"
    
    node ntc out
    prop label "N2 tube cool delay"
    
    node ntm out
    prop label "N2 fill timeout"
    
    node ns upd -int
    prop enum sens_ok,no_sens,short_circuit,upside_down,sens_warm,empty
    
    node na out -int
    prop enum 1
    prop label "N2 auto fill"
    
    node nv upd -int
    prop enum fill_valve_off,filling,no_fill_valve,timeout,timeout1
    
    node nc out -int
    prop enum stop,fill,off,auto
        
    node cda upd
    prop label "code res. a"
  
    node cdb upd
    prop label "code res. b"
    
    node cba upd
    prop label "code a invalid"
  
    node cbb upd
    prop label "code b invalid"
  
    node cvs -int upd
    prop label "config version"
  
    node csp -int upd
    prop label "hardware type"
  
    node cdv out -text
    prop label "device"
  
    node cds out
    prop label "device state"
    prop enum local,remote,loading,by_code,by_touch
  
    node tc upd
    node tn upd
    node th upd
    node tf upd
    node tm upd
    node tv upd
    node tq upd
    
    node hfb upd
    node nfb upd

    node bdl out
    prop label "valve boost delay"

  }
  return "CCU4"
} 

proc ccu4_6::completeStart {} {
  set cid 0
  stdSct::scanf {cid=%s csf=%s} cid csf
  sct result $cid
  set old [silent 0 result device ccu4version]
  if {$old ne $csf} {
    catch {device makeitem ccu4version $csf}
    error "WARNING: CCU4 version has changed from $old to $csf, please make 'samenv reload'"
  }
  hsetprop [sct parent] freelist ""
  return [stdSct::completeStart]
}

proc ccu4_6::errorScript {} {
  hupdate [sct obj]/status [sct result]
  stdSct::errorScript
}

proc ccu4_6::read {} {
  if {![hvali [sct]]} {
    sct update 0
    return idle
  }
  sct update 1
  sct send "?"
  return ccu4_6::update 
}

proc ccu4_6::loadcodes {} {
  if {[sct codeidx] >= [sct codelen]} {
# set version and save
    sct send "cvs=[sct codeversion] c=s"
    clientput "CCU4: updated cfgtable to version from [clock format [sct codeversion] -format {%Y-%m-%d %H:%M}]"
    return ccu4_6::loadcomplete
  }
# add item to device list
  sct send "c=[lindex [sct codelist] [sct codeidx]]"
  sct codeidx [expr [sct codeidx] + 1]
  return stdSct::complete
}

proc ccu4_6::loadcomplete {} {
  hupdate [sct]/cvs [sct codeversion]
  return unpoll
}

proc ccu4_6::update {} {
  variable deviceaction
  variable newdevice
  
  hupdate [sct]/status ""
  catch {device ccu4_available 1}
  set fdone 0
  foreach item [sct result] {
    set item [split $item "="]
    
    if {[catch {
        set name [lindex $item 0]
        set value [lindex $item 1]
        if {"$name" eq "f"} {
          set fdone 1
        } elseif {$name eq "cds"} {
          if {$value >= 3 || $value == 0} { # device changed
            set deviceaction $value
          }
          set newdevice ""
        } elseif {$name eq "cdv" && $deviceaction >= 3} {
          set newdevice $value
        }
        set errvar [silent "" hgetpropval [sct]/$name errvar]
        if {$errvar ne ""} {
          set errval [hvali [sct]/$errvar]
          if {$errval > 0} {
            hsetprop [sct]/$name geterror [lindex [split [hgetpropval [sct]/$errvar enum] ,] $errval]
            hupdate [sct]/$name $value
          } else {
            updateval [sct]/$name $value
          }
        } else {
          updateval [sct]/$name $value
        }
      } msg]} {
      clientput $msg
      clientput $item
    }
  }
  # update flow anyway, as this triggers control
  if {!$fdone} {
    hupdate [sct]/f [hvali [sct]/f]
  }
  hdelprop [sct] geterror
  set cvs [hvali [sct]/cvs]
  if {$cvs != 0 && [file exists [sct cfgtablefile]]} {
    sct codeversion [file mtime [sct cfgtablefile]]
    
    if {$cvs != [sct codeversion]} {
      clientput "CCU4: replace cfgtable version from [clock format $cvs -format {%Y-%m-%d %H:%M}]"
      hupdate [sct]/cvs 0
      set fil [open [sct cfgtablefile]]
      set codelist [list ]
      foreach line [split [::read $fil] \n] {
        if {[string index $line 0] ne "#" && [string length $line] > 1} {
          set lline [split $line "\t"]
          while {[llength $lline] < 6} {
            lappend lline {}
          }
          lappend codelist [join $lline ","]
        }
      }
      sct codelist $codelist
      close $fil
      sct codeidx 0
      sct codelen [llength [sct codelist]]
      sct send "cvs=0 c=c"
      [sct controller] poll [sct] 0.1 slow ccu4_6::loadcodes
      return stdSct::complete
    }
  }
  if {$deviceaction == 0} {
    # CCU4 was restarted
    device makeitem action renew
    sct send cds=1
    set deviceaction 1
    return stdSct::complete
  }
  if {$deviceaction >= 3} {
    if {$newdevice eq ""} {
      # get new device name
      sct send cdv
      return ccu4_6::update
    }
    if {[sctval [sct]/autodevice]} {
      device makeitem newdevice [string tolower $newdevice]
      if {$deviceaction == 3} {
        device makeitem action "plugged"
      } else {
        device makeitem action "selected on touch display"
      }
      # set device state to "loading"
      clientput loading
      sct send cds=2
    } elseif {$deviceaction == 3} {
      clientput "plugged [string tolower $newdevice] but autodevice off"
      # set device state to "remote"
      sct send cds=1
    } else {
      clientput "[string tolower $newdevice] selected on CCU4, but autodevice off"
      # set device state to "remote"
      sct send cds=1
    }
    set deviceaction 1
    return stdSct::complete
  }
  return idle
}

proc ccu4_6::write {} {
  if {![hvali [sct parent]]} {
    sct update [sct target]
    return idle
  }
  set name [lindex [split [sct] "/"] 2]
#clientput "[expr [clock seconds] % 60] $name=[sct target]"
  sct send "$name=[sct target]"
  return ccu4_6::complete
}

proc ccu4_6::complete {} {
  set res [split [sct result] "="]
  sct update [lindex $res 1]
  return idle
}


