#----------------------------------------------------------------------------
#                            H A K L E
#
# Driver for the Haake water bath thermostat in the SINQ setup. This driver
# is realised in Tcl and uses the tclev interface for talking to SICS.
#
# copyright: see copyright.h
#
# Mark Koennecke, February 1998
#----------------------------------------------------------------------------
set HakleNUM 0

proc HakleSend args {
     upvar #0 [lindex $args 0] ar
     set command [lrange $args 1 end]
     set ret [catch {$ar(socket) $command} msg]
     if {$ret != 0} {
        ClientPut $msg
        error -701
     } 
     return $msg
}
#--------------------------------------------------------------------------
# HakleCheck tests a answer from the Hake for validity. Valid answers
# contain a $. Errors no $ and and F as first character. 
proc HakleCheck {text } {
     if { [string match *\$ $text]} {
       return 1
     }
     if { [string match F* $text] } {
      error -703
     }
}
#---------------------------------------------------------------------------
proc HakleCommand args { 
     upvar #0 [lindex $args 0] ar
     set ret [catch {eval HakleSend $args} msg]
     if {$ret != 0} {
        error $msg
     } 
     set ret [catch {HakleCheck $msg} msg2]
     if {$ret != 0} {
        error $msg2
     }
     return $msg
}
#----------------------------------------------------------------------------
proc HakleInit {Hakle} {
     upvar $Hakle ar
     global HakleNUM 
#------ open a connection
     set nam hakle$HakleNUM
     set ret [catch {serialport $nam $ar(computer) $ar(port) \
             $ar(channel) 1} msg]
     if {$ret != 0 } {
        ClientPut $msg
        error -700
     } 
     set ar(socket) $nam
     incr HakleNUM
     set ar(intern) 1
     set ar(pending) 0
     set ar(lastread) 20.00
#----- configure
     $nam -replyterm "1\r"
     $nam -tmo 1800
#----- block local
     set ret [catch {HakleCommand $Hakle OUT MODE 3 0} msg ]
     if {$ret != 0 } {
        error -$msg
     } 
    return 1
}
#---------------------------------------------------------------------------
proc HakleClose {Hakle} {
     upvar #0 $Hakle ar
     set ret [catch {HakleCommand $Hakle OUT MODE 3 1} msg]
     if {$ret != 0} {
        ClientPut "Error resettting Haake Thermostat"
     }
     rename $ar(socket) ""
     return 1
}
#----------------------------------------------------------------------------
proc HakleWrapper args {
     upvar #0 [lindex $args 0] ar
     if { [llength $args] < 2 } {
        error "Insufficient number of commands"
     }
     set key [lindex $args 1]
     switch -exact $key {
        sensor {
          if { [llength $args] > 2 } {
             set val [lindex $args 2]
#------- switch to intern
             if { [string compare $val intern] == 0 } {
               set ret [catch {HakleCommand [lindex $args 0] OUT MODE 2 0} msg]
               if {$ret != 0 } {
                   error $msg
                } else {
                  set ar(intern) 1
             }
#-------- switch to extern
             } elseif { [string compare $val extern] == 0 } {
               set ret [catch {HakleCommand [lindex $args 0] OUT MODE 2 1} msg]
               if {$ret != 0 } {
                   error $msg
               } else {
                  set ar(intern) 0
               }
             } else {
               error -705
             }
          } else {
            if { $ar(intern) == 1 } {
               ClientPut [format "%s.sensor intern" $ar(MyName)]
               return 1
            } else {
               ClientPut [format "%s.sensor extern" $ar(MyName)]
               return 1
            } 
          }
        }
        list {
            if { $ar(intern) == 1 } {
               ClientPut [format "%s.sensor intern" $ar(MyName)]
               error -700
            } else {
               ClientPut [format "%s.sensor extern" $ar(MyName)]
               error -700
            } 

        }
        default {
                error -700
        }
     }
}
#----------------------------------------------------------------------------
proc HakleSet {Hakle val} {
     upvar #0 $Hakle ar
#     ClientPut "HakleSet"
     set ret [catch {$ar(socket) [format "OUT SP 1   %f" $val]} msg]
     if {$ret != 0} {
        ClientPut $msg
        error -701
     } 
     set ret [catch {HakleCheck $msg} msg2]
     if {$ret != 0} {
        error $msg2
     }
     set ar(pending) 0
     return $msg
}
#----------------------------------------------------------------------------
proc HakleGet {Hakle} {
     upvar #0 $Hakle ar
     if {$ar(intern) == 1} {
        set ret [catch {eval HakleCommand $Hakle IN PV 1} msg]
        if {$ret != 0 } {
          error $msg
         }
     } else {
        set ret [catch {HakleCommand IN PV 2} msg]
        if {$ret != 0 } {
          error $msg
         }
     }
     set ans  [string trim $msg \$]
     set ans2 [string trim $ans]
     set ans3 [string trim $ans2 C]
#------ fix some pecularities of the Haake, sometimes it gives empty
#       messages or double +
     if { [string length $ans3] < 3 } {
        return $ar(lastread)
     } 
     if { [string first "++" $ans3] >= 0 } {
       set ans3 [string range $ans3 1 end]
     }
     set ar(lastread) $ans3
     return $ans3   
}
#----------------------------------------------------------------------------
proc HakleGet2 {Hakle} {
     upvar #0 $Hakle ar
#     ClientPut "HakleGet"
     if {$ar(pending) == 0} {
       if {$ar(intern) == 1} {
          set ret [catch {$ar(socket) -put IN PV 1} msg]
          if {$ret != 0 } {
             ClientPut $msg
             error -701
          }
       } else {
           set ret [catch {$ar(socket) -put IN PV 2} msg]
           if {$ret != 0 } {
              ClientPut $msg
              error -701
           }
       }
       set ar(pending) 1
       return $ar(lastread)
     } else {
         if {[$ar(socket) -readable] == 1 } {
            set ar(pending) 0
            set ret [catch {$ar(socket) -get} msg]
            if {$ret != 0 } { 
               ClientPut $msg
               error -701
            }
            set ans  [string trim $msg \$]
            set ans2 [string trim $ans]
            set ans3 [string trim $ans2 C]
            set ar(lastread) $ans3
            return $ans3
         } else {
            return $ar(lastread)
         }
     }   
}
#-----------------------------------------------------------------------------
proc HakleError {Hakle val} {
     upvar #0 $Hakle ar
     switch -exact -- $val {
        -700 {
           return "Cannot open socket"
        }
        -701 {
           return "Error sending command"
        }
        -703 {
           return "Invalid command sent"
        }
        default {
           return "Unknown error code"
        }
     } 
}
#-----------------------------------------------------------------------------
proc HakleFix {Hakle val} {
     upvar #0 $Hakle ar
     switch -exact -- $val {
        -700 {
           return DEVFAIL
        }
        -701 {
             return DEVREDO
         }
        -703 {
           return DEVREDO
        }
        default {
           return DEVFAIL
        }
     } 
}
#----------------------------------------------------------------------------
proc inihaakearray {ar comp port chan} {
     upvar #0 $ar Hakle
     set Hakle(Init) HakleInit
     set Hakle(Close) HakleClose
     set Hakle(Send)  HakleSend
     set Hakle(SetValue) HakleSet
     set Hakle(GetValue) HakleGet
     set Hakle(GetError) HakleError
     set Hakle(TryFixIt) HakleFix
     set Hakle(Wrapper) HakleWrapper
     set Hakle(computer) $comp
     set Hakle(port)     $port
     set Hakle(channel)  $chan
     set Hakle(num)      0
     set Hakle(lastread) 20.00
}
