#!/usr/bin/tclsh set ::test 0 set ::debug 1 set ::ontime 30 set ::lockfile /var/lock/doormonitor set ::owfs /mnt/1wire if {$test} { set ::sensor 12.0C4A02000000 set ::sensoract $::sensor/latch.B set ::sensorinit [list \ [list $::sensor/set_alarm 211] \ [list $::sensor/PIO.ALL 0,0] \ [list $::sensor/latch.ALL 0,0] \ ] } else { set ::sensor 12.8C4229000000 set ::sensoract $::sensor/latch.A set ::sensorinit [list \ [list $::sensor/set_alarm 111] \ [list $::sensor/PIO.ALL 0,0] \ [list $::sensor/latch.ALL 1,1] \ ] } set ::driver 12.90D21C000000 set ::driverpio $::driver/PIO.A set ::driverinit [list \ [list $::driver/set_alarm 011] \ [list $::driver/PIO.A 0] \ [list $::driver/latch.ALL 1,1] \ ] proc logger {msg {priority err}} { syslog -facility daemon -ident doormonitor $priority $msg } proc owget {name} { if {[catch {open $::owfs/$name} f]} { logger "ERROR: $f" return "" } set res [read -nonewline $f] close $f return $res } proc owput {name {val ""}} { if {[catch {open $::owfs/$name WRONLY} f]} { logger "ERROR(owput): $f" return 0 } puts $f $val close $f return 1 } proc IsActivity {} { return [owget $::uncached$::sensoract] } proc ClearActivity {} { if {$::debug} { logger ClearActivity info } owput $::sensoract 1 } proc DoInit {{dev ""}} { if {($dev=="") || ($dev==$::sensor)} { if {$::debug} {logger "sensor init" info} foreach l $::sensorinit {owput [lindex $l 0] [lindex $l 1]} ClearActivity } if {($dev=="") || ($dev==$::driver)} { if {$::debug} {logger "driver init" info} foreach l $::driverinit {owput [lindex $l 0] [lindex $l 1]} } } proc TurnOn {} { if {$::debug} { logger "driver ON" info } owput $::driverpio 1 } proc TurnOff {} { if {$::debug} { logger "driver OFF" info } owput $::driverpio 0 file delete -force $::lockfile } proc ReadLockFile {} { if {[catch {open $::lockfile} lck]} { logger "ERROR: $lck" return "" } set str [string trim [gets $lck]] close $lck if {[regexp {^(\d+)\s+(\d+)$} $str foo pid tim]} { return [list $pid $tim] } else { logger "ERROR: Bad data in $::lockfile" return "" } } proc UpdateLockfile {pid tim} { if {[catch {open $::lockfile w} lck]} { logger "ERROR: $lck" return 0 } puts $lck "$pid $tim" close $lck return 1 } proc CheckProcess {pid} { # return: # 0 - error # 1 - process not found # 2 - process exists global errorCode if {[catch {kill 0 $pid} msg]} { if {[lindex $errorCode 1] == "ESRCH"} { if {$::debug} {logger "process not found" info} return 1 } else { logger "ERROR: Cannot send signal to process($pid): $msg" return 0 } } else { if {$::debug} {logger "process exists" info} return 2 } } proc TurnOnAndWait {} { if {[UpdateLockfile [pid] [clock seconds]] == 0} { exit 1 } TurnOn set difftime $::ontime while {1} { after [expr $difftime * 1000] set currtime [clock seconds] if {[set old [ReadLockFile]] == ""} { TurnOff exit 1 } set stoptime [expr [lindex $old 1] + $difftime] if {$stoptime <= $currtime} { TurnOff exit 0 } else { set difftime [expr $stoptime - $currtime] } } } if {($argc < 1) || (([set mode [lindex $argv 0]] != "init") && ($mode != "start"))} { puts stderr "Usage: $argv0 init [device]|start" exit 1 } package require Syslog package require Tclx if {[file exists $::owfs/uncached]} {set ::uncached uncached/} {set ::uncached ""} if {$mode == "init"} { DoInit [lindex $argv 1] TurnOff exit 0 } if {$mode == "start"} { if {![IsActivity]} { # exit 0 } ClearActivity if {[file exists $::lockfile]} { if {[set old [ReadLockfile]] == ""} {exit 1} switch [CheckProcess [lindex $old 0]] { 0 {exit 1} 1 TurnOnAndWait 2 { if {[UpdateLockfile [lindex $old 0] [clock seconds]]} { exit 0 } else { exit 1 } } } } else { TurnOnAndWait } exit 0 }