fhem.pl command reference
You can use all of the following commands in in two ways:
There are three types of commands: "fhz" commands (described in this document),
shell commands (they must be enclosed in double quotes ") and perl expressions
(enclosed in curly brackets {}). shell commands or perl expressions are needed for
complex at or notifyon arguments.
Shell commands will be executed in the
background, the perl program and the fhz commands will be executed in the main
"thread".
In order to make perl expressions easier to write, some special functions and
variables are available. See the section Perl special for a
description.
To trigger "fhz" commands from a shell script, use the client form of
fhem.pl (described above).
Multiple fhz commands are separated by semicolon (;). In order to use semicolon
in perl code or shell programs, they have to be escaped by the double semicolon
(;;).
Commands can be either typed in plain, or read from a file (e.g. the
configuration file at startup). The commands are either executed directly, or
later if they are arguments to the at and notifyon fhz commands.
If commands are read from a file, then a line ending with \ will be
concatenated with the next one, so long lines (e.g. perl oneliners) can be
split in multiple lines
?, help
?
help
Get a list of all commands and short description for each one
at
at <timespec> <command>
Start an arbitrary fhem.pl command at a later time.
<timespec>
format: [+][*]HH:MM:SS
The optional +
indicates that the specification is
relative(i.e. it will be added to the current time).
The optional *
indicates that the command should be
executed repeatedly.
The optional {N}
after the * indicates,that the command
should be repeated N-times only.
Examples:
# absolute ones:
at 17:00:00 set lamp on # fhz command
at 17:00:00 { Log 1, "Teetime" } # Perl command
at 17:00:00 "/bin/echo "Teetime" > /dev/console" # shell command
at *17:00:00 set lamp on # repeat every day
# relative ones
at +00:00:10 set lamp on # switch the lamp on in 10 seconds
at +00:00:02 set lamp on-for-timer 1 # Blink once in 2 seconds
at +*{3}00:00:02 set lamp on-for-timer 1 # Blink 3 times
# Blink 3 times if the piri sends a command
notify piri:on.* at +*{3}00:00:02 set lamp on-for-timer 1
# Switch the lamp on from sunset to 11 PM
# Copy 99_SUNRISE.pm in the FHEM directory to have sunset_rel()
{ sunrise_coord("8.686", "50.112", "Europe/Berlin") }
at +*{sunset_rel()} set lamp on
at *23:00:00 set lamp off
# More elegant version, works for sunset > 23:00 too
at +*{sunset_rel()} set lamp on-till 23:00
# Only do this on weekend
at +*{sunset_rel()} { fhz("set lamp on-till 23:00") if($we) }
# Switch lamp1 and lamp2 on from 7:00 till 10 minutes after sunrise
at *07:00 set lamp1,lamp2 on-till {sunrise_abs(+600)}
# Switch the lamp off 2 minutes after sunrise each day
at +*{sunrise_rel(+120)} set lamp on
Notes:
- if no
*
is specified, then a command will be executed
only once, and then the at
entry will be deleted.
- if the current time is greater then the time specified, then the
command will be executed tomorrow. This is why the relative forms
of the sunset/sunrise functions should be used with the relative
(+) flag
- the
delete
argument for at is the
complete line as it appears in list
(with spaces), but you can use regexps.
- In order to use the sunrise_rel()/sunset_rel() functions, copy the
99_SUNRISE.pm file from the contrib into the modules (FHEM)
directory, and put { sunrise_coord(long, lat, tz) } into your config
file, as in the above example. If you are not using sunrise_coord, then
the coordinates for Frankfurt am Main, Germany will be used.
You also have to install the Datetime::Event::Sunrise perl module.
- do not place
at
commands in the config file if you
specified a savefile
, as all
at
commands will be saved there too, and then defined
twice at startup. at
is intended to be inserted by
hand or by cronjobs.
- For more complex date handling you either have to call fhem from
cron or filter the date in a perl expression, see the last example and
the section Perl special.
attr
attr <devname> <attrname> [<value>]
or
attr at <at-spec-regexp> <attribute>
Set a device,log or at attribute. There are some special attributes used
by the fhem.pl itself or the web-frontends, but you can define your own to
use them in other applications.
Recognized attributes:
- room
Filter/group devices. Recognized by web-pgm2 and web-pgm3.
Devices in the room hidden will not appear in the web output.
- loglevel
Set the device loglevel to e.g. 6 if you do not wish messages from a
given device to appear in the global logfile (FHZ/FS20/FHT). E.g. to
set the FHT time, you should schedule "set FHZ time" every minute, but
this in turn makes your logfile unreadable. These messages will not be
generated if the FHZ attribute loglevel is set to 6.
- dummy
Set the device attribute dummy to define devices which should not
output any radio signals. Associated notifyons will be executed if
the signal is received. Used e.g. to react to a code from a sender, but
it will not emit radio signal if triggered in the web frontend.
Implemented for FS20 and FHT devices.
- do_not_notify
Disable FileLog/notify/inform notification for a device. This affects
the received signal, the set and trigger commands.
- skip_next
Used for at commands: skip the execution of the command the next time.
- follow-on-for-timer
the program automatically schedules a "setstate off" for the time
specified as argument to the on-for-timer command (for the specified
device only).
- repeater
Set the attribute "repeater" for an FHZ device to 1 to ignore events
received from a FS20 repeater. In fact we are not sure that they are
repeater messages, we just ignore messages which were sent out by our
device for the next 3 seconds (see the next attribute)
- filtertimeout
Ignore duplicate messages for this amount of time. The time is in
seconds, fractions are allowed. It affects installations with more then
one FHZ device or repeater, see the entry above.
Examples:
attr lamp room kitchen
attr lamp dummy
attr lamp loglevel 6
del attr lamp
at *23:00:10 set lamp off
attr at lamp.off skip_next
Notes:
- There is no way to delete a single attribute.
define
define <name> <type> <type-specific>
Define a device. You need devices if you want to manipulate them (e.g.
set on/off), and the logfile is also more readable if it contains e.g.
"lamp off" instead of "Device 5673, Button 00, Code 00 (off)".
Type FHZ:
define <name> FHZ <serial-device>
Specifies the serial port to communicate with the FHZ 1000 PC. The name(s)
of the serial-device(s) depends on your distribution. The program can
service multiple devices, FS20 and FHT device commands will be sent out
through the last FHZ device defined before the definition of the FS20/FHT
device. To change the association, use the set command
activefor. Important: this definition must occur after the
modpath command but before any other (FHZ related) device definition,
else you'll see "no I/O device found" messages.
If the serial-device is called none, then no device will be opened, so you
can experiment without hardware attached.
Set the attribute "repeater" for this device to 1 to ignore events received
from a FS20 repeater. In fact we are not sure that they are repeater
messages, we just ignore messages which were sent out by our device for the
next 3 seconds (or configured otherwise by filtertimeout).
Type FS20:
define <name> FS20 <housecode> <button>
[fg <fgaddr>] [lm <lmaddr>] [gm FF]
<housecode>
is a four digit hex number,
corresponding to the housecode address, <button>
is
a two digit hex nunmber, corresponding to a button of the transmitter.
- The optional fg specifies the function group, the first digit of the 2
digit adress must be F.
- The optional lm specifies the local master, the last digit of the 2
digit adress must be F.
- The optional gm specifies the global master, the adress must be FF.
Examples:
define lamp FS20 7777 00 fg F1
define roll1 FS20 7777 01
Type FHT:
define <name> FHT <housecode>
<housecode>
is a four digit hex number,
corresponding to the adress of the FHT80b device.
Examples:
See the section set for more.
Type HMS:
define <name> HMS <housecode>
<housecode>
is a four digit hex number,
corresponding to the adress of the HMS device.
Examples:
Notes:
- There is _NO_ guarantee that the code will work as expected in all
circumstances, the authors are not liable for any damage occuring as a
result of incomplete or buggy code
- Currently supported devices are the HMS100T, HMS100TF, HMS100WD and
the RM100-2.
- The housecode of the HMS devices may change if the battery is renewed.
In order to make life easier, you can define a "wildcard" device for each
type of HMS device. First the real device-id will be checked, then the
wildcard device id. The wildcards are:
- 1000 for the HMS100TF
- 1001 for the HMS100T
- 1002 for the HMS100WD
- 1003 for the RM100-2
- 1006 for the HMS100MG
- Some battery low notifications are not yet implemented (RM100, HMS100WD).
- Please test your installation before relying on the functionality.
Type KS300:
define <name> KS300 <housecode> [ml/raincounter [wind-factor]]
<housecode>
is a four digit hex number,
corresponding to the adress of the KS300 device, right now it is ignored.
The ml/raincounter defaults to 255 ml, but it must be specified if you wish
to set the wind factor, which defaults to 1.0.
Examples:
Type WS300:
define WS300Device WS300 <serial device>
or
define <devname> WS300 [0-9]
The first line is mandatory if you have a WS300 device: it defines the
input device with its USB port. The name of this device is fixed and must
be WS300Device. It must be the first defined WS300 device.
For each additional device (with number 0 to 9) you have to define another
WS300 device, with an arbitrary name. The WS300 device which reports the
readings will be defined with the port number 9, an optional KS300 with the
port number 8.
Examples:
define WS300Device WS300 /dev/ttyUSB1
define ash2200-1 WS300 0
define ks300 WS300 8
define ws300 WS300 9
Type FileLog:
define <name> FileLog <filename> <regexp>
Log events to <filename>
. The log format is
YYYY:MM:DD_HH:MM:SS <device> <event>
The regexp will be checked against the (complete!) device name
or against the (complete!) devicename:event combination.
<filename>
may contain one or more of the following
wildcards (a subset of the Unix date command arguments):
%d
day of month (01..31)
%m
month (01..12)
%Y
year (1970...)
%w
day of week (0..6); 0 represents Sunday
%j
day of year (001..366)
%U
week number of year with Sunday as first day of week (00..53)
%V
week number of year with Monday as first day of week (01..53)
Examples:
define lamplog FileLog /var/tmp/lamp.log lamp
define wzlog FileLog /var/tmp/wz-%Y-%U.log
wz:(measured-temp|actuator).*
delete
delete {def|ntfy|at} <name>
Delete a definition, a
notifyon setting or an at command.
The <name>
argument has to be the first column of
the list output (as in case of at least at
it is not obvious).
Examples:
delete def lamp
delete at 22:15:00 set lamp off
Notes:
- The program first tries to find the exact
<name>
, if
it is not found, then it will try it as a regexp, so you can also specify
delete at .*lamp.*
to delete the at command above.
- Do not use doubleqoutes ("e;) in
<name>
, only if
you used them in your definition.
get
get <name> <type-specific>
Ask a value directly from the device, and wait for an answer. In general, you
can get a list of possible commands by
get <device>
help
Right now only the FHZ module supports this function.
Type FHZ:
get FHZ <value>
where value
is one of:
init1
init2
init3
serial
fhtbuf
Notes:
- There is only one FHZ device (called FHZ), it is created automatically
at startup.
- The mentioned codes are needed for initializing the FHZ1000
- The answer for a command is also displayed by
list FHZ
-
fhtbuf
should be incorporated later in the FHT
module:
the FHZ1000PC has a message buffer for the FHT, as it
only can send messages to it every 2 (or so) minutes. If the buffer
is full, then newly issued ones will be dropped. fhtbuf
returns the free memory in this buffer (in hex), my maximum is 2c (42
bytes).
include
include <filename>
Read in the file, and process every line as a fhem command. Makes
configuration files more modular and enables to reread them.
inform
inform [on|off]
If set to on, and a device state changes, send a notification to the current
client. This command can be used by other programs/modules to receive a
notification.
list
list [name]
Output a list of all definitions, all notifyon settings and all at
entries. This is one of the few commands which return a string in a
normal case.
Example:
FHZ> list
Type list for detailed info.
FHZ devices:
FHZ (Last msg: Initialized)
FS20 devices:
Btn3 (Last msg: off)
Roll1 (Last msg: on-for-timer 11)
Stehlampe (Last msg: off)
FHT devices:
fl (Last msg: state: Bat: ok, Window: closed)
wz (Last msg: actuator: 07%)
NotifyOn:
Btn3 /usr/local/bin/setroll %
At:
+*{sunrise_rel(+10)} set Roll1 on-for-timer 10 (07:43:56)
Logs:
wzlog FileLog /var/tmp/wz.log wz:.*(temp|actuator).*
If specifying name
, then a detailed status for name
will be displayed, e.g.:
FHZ> list wz
2006-01-03 18:28:27 actuator 07%
2006-01-03 18:26:32 mon-from1 06:00
2006-01-03 18:26:33 mon-to1 23:00
2006-01-03 18:26:34 tue-from1 06:00
2006-01-03 18:26:34 tue-to1 23:00
2006-01-03 18:26:35 wed-from1 06:00
2006-01-03 18:26:35 wed-to1 23:00
2006-01-03 18:26:37 thu-from1 06:00
2006-01-03 18:26:37 thu-to1 23:00
2006-01-03 18:26:38 fri-from1 06:00
2006-01-03 18:26:38 fri-to1 23:00
2006-01-03 18:26:39 sat-from1 06:00
2006-01-03 18:26:40 sat-to1 23:50
2006-01-03 18:26:41 sun-from1 06:00
2006-01-03 18:26:41 sun-to1 23:00
2006-01-03 18:26:45 mode manual
2006-01-03 18:26:44 desired-temp 21.5 (Celsius)
2006-01-03 18:26:45 measured-temp 22.0 (Celsius)
2006-01-03 18:26:46 state Bat: ok, Window: closed
2006-01-03 18:24:37 init 255
2006-01-03 18:26:42 day-temp 21.0 (Celsius)
2006-01-03 18:26:42 night-temp 17.0 (Celsius)
2006-01-03 18:26:43 unknown_85 4
2006-01-03 18:26:43 windowopen-temp 12.0 (Celsius)
logfile
logfile
Specify the logfile to write. Specify this as the first command in the
configfile as everything gets logged in the logfile. You can use "-" for
stdout, in this case the server won't background itself.
The logfile name can also take wildcards for easier logfile rotation,
see the FileLog section of the define command.
Examples:
logfile /var/log/fhem
logfile /var/log/fhem-%Y-%m.log
modpath
modpath <path>
Specify the path to the modules directory FHEM
. The path
should not contain the directory FHEM. Every module there will
be loaded.
Example:
notifyon
notifyon <name> <command>
Execute a command when received an event for the definition <name>
. As with normal
commands, if it is enclosed in {}, then it is a perl expression, if it is
enclosed in "", then it is a shell command, else it is a "plain" fhem.pl
command (chain). See the trigger command for testing
it.
Examples:
notifyon btn3 set lamp %
notifyon btn3 { fhz "set lamp %" }
notifyon btn3 "/usr/local/bin/setlamp "%""
notifyon btn3 set lamp1 %;;set lamp2 %
notifyon wz:measured.* "/usr/local/bin/logfht @ "%""
notifyon .*H:.* {DbLog("@","%")}
notifyon UNDEFINED "send-me-mail.sh "%""
Notes:
- The character
%
will be replaced with the received event,
e.g. with on
or off
or measured-temp: 21.7
(Celsius)
It is advisable to put the %
into double
quotes, else the shell may get a syntax error.
To use % or @ in the text itself, use the double mode (%% or @@)
- The character
@
will be replaced with the device
name.
<name>
may also be a compound of
definition:event
to filter for events.
<name>
is in fact a regexp. It must completely (!)
match either the device name, or the compound of the device name and the
event. The event is either the string you see in the list output in paranthesis after the device name, or the
string you see when you do a detailed list of the device.
- To use database logging, copy the file contrib/91_DbLog.p into your
modules directory, and change the $dbconn parameter in the file.
- Each undefined device (FS20, HMS, FHT) will be reported with the device
name "UNDEFINED". The % parameter will contain the type (FS20, HMS100T,
etc) and device number, separated by a space.
pidfile
pidfile <filename>
Write the process id of the perl process to the specified file. We are
running as a daemon, and some distributions would like to check by the pid if
we are still runnning.
Example:
pidfile /var/run/fhem.pid
port
port <number> [<global>]
Listen on the TCP/IP port <number>
for incoming
connections. To offer at least a little bit of security, the server will only
listen for connections from the localhost per default. The optional global
parameters enables listening for non-localhost connections too.
Example:
quit
quit
If used in a TCP/IP session, terminate the client session.
If used in a script, terminate the parsing of the script.
Example:
reload
reload <module>
Reload the given module from the module directory. Mainly intended to reload
the 99_PRIV file (or equivalent) in order to test perl-scripts.
Example:
rereadcfg
rereadcfg
Re-read the configuration file.
Note: The statefile will be saved first, then the config file will be read
(all devices will be initialized again), and at last the statefile will be reloaded again.
Example:
savefile
savefile <filename>
Set the filename where the state and at information will
be saved before shutdown. If not setting it, then no information will be
saved.
Example:
savefile /var/tmp/fhem.save
set
set <name> <type-specific>
Set parameters of a device / send signals to a device. In general, you can
get a list of possible commands by
set <device> help
Instead of <name> you can also use an enumeration (separated by comma)
or ranges (separated by -), see the FS20 examples.
Type FHZ:
set FHZ <variable> [<value>]
where value
is one of:
initFS20
initHMS
time
FHTcode
activefor
raw
Notes:
- use activefor if you have multiple FHZ devices, and you want to change the association
of an FS20 or FHT device (i.e. which device will send out the messages).
- raw is used to send out "raw" FS20/FHT messages. See the doc
directory for some examples
- In order to set the time of your FHT's, schedule this command every minute:
at +*00:01:00 set FHZ time
See the attr command to prevent logging of this command.
- FHTcode is a two digit hex number (from 00 to 63?) and sets the central
FHT code, which is used by the FHT devices. After changing it, you
must reprogram each FHT80b with: PROG (until Sond appears), then
select CEnt, Prog, Select nA.
Type FS20:
set <name> <value> [<time>]
where value
is one of:
dim06%
dim12%
dim18%
dim25%
dim31%
dim37%
dim43%
dim50%
dim56%
dim62%
dim68%
dim75%
dim81%
dim87%
dim93%
dim100%
dimdown
dimup
dimupdown
off
off-for-timer
on # dimmer: set to value before switching it off
on-for-timer # see the note
on-old-for-timer # set to previous (before switching it on)
ramp-on-time # time to reach the desired dim value on dimmers
ramp-off-time # time to reach the off state on dimmers
reset
sendstate
timer
toggle # between off and previous dim val
on-till # Special, see the note
Examples:
set lamp on
set lamp1,lamp2,lamp3 on
set lamp1-lamp3 on
set lamp on-for-timer 12
Notes:
- Use reset with care: the device forgets even the housecode.
- As the FS20 protocol needs about 0.22 seconds to transmit a
sequence, a pause of 0.22 seconds is inserted after each command.
- The FS20ST switches on for dim*%, dimup. It does not respond to
sendstate.
- If the timer is set (i.e. it is not 0) then on, dim*,
and *-for-timer will take it into account (at least by the FS20ST).
- The
time
argument ranges from 0.25sec to 4 hours and
16 minutes.
As the time is encoded in one byte (there are only 112 distinct
values), the resolution gets coarse with larger values. The program
will report the used timeout if the specified one cannot be set
exactly. The resolution is 0.25 sec from 0 to 4 sec, 0.5 sec from 4
to 8 sec, 1 sec from 8 to 16 sec and so on. If you need better
precision for large values, use the at command
which has a 1 sec resolution.
- If the attribute follow-on-for-timer is set for the device and the
on-for-timer command is sent to the device with a time parameter,
the program automatically schedules a "setstate off" for the
specified time.
- on-till requires an absolute time in the "at" format (HH:MM:SS, HH:MM
or {}, where the perl-code returns a time specification).
If the current time is greater then the specified time, then the
command is ignored, else an "on" command is generated, and for the
given "till-time" an off command is scheduleld via the at command.
Type FHT:
set <name> <valuetype> <value>
where value
is one of:
mon-from1
mon-to1
mon-from2
mon-to2
tue-from1
tue-to1
tue-from2
tue-to2
wed-from1
wed-to1
wed-from2
wed-to2
thu-from1
thu-to1
thu-from2
thu-to2
fri-from1
fri-to1
fri-from2
fri-to2
sat-from1
sat-to1
sat-from2
sat-to2
sun-from1
sun-to1
sun-from2
sun-to2
mode
desired-temp
day-temp
night-temp
year
month
day
hour
minute
refreshvalues
Notes:
- All
*-temp
valuetypes need a temperature
as argument, which will be rounded to 0.5 Celsius
mode
is one of auto, manual or holiday
- The
*-from1/*-from2/*-to1/*-to2
valuetypes need a time
spec as argument in the HH:MM format. They define the periods, where
the day-temp is valid. The minute (MM) will be rounded to 10, and
24:00 means off.
refreshvalues
does not need an argument, but sends a
plea to the FHT device, so it may send its parameters. If you want
to get these values regularly, then schedule:
at +*01:00:00 set <name> refreshvalues
My two FHT devices send the actuator, measured-temp and state
regularly, and everything else if it changes, so I do not schedule
this normally.
- The FHT is very economical (or lazy), it receives messages from the
FHZ1000 every 2 minutes (or so). Don't be surprized if your command
is accepted 10 minutes later by the device. See the related
fhtbuf
entry in the get
section.
Type FHT:
set WS300Device <interval(min.)> <height(m)> <rainvalume(ml)>
Set some WS300 configuration parameters.
setstate
setstate <name> <value>
Set the "Last msg" for the definition
<name>
shown in the list command
to <value>
without sending any signals to the device
itself. This command is also used in the savefile.
Setting/changing arbitrary comments is possible, if the value begins with
comment:. To delete the comment, set it with an empty value,
see below.
Examples:
setstate lamp on
setstate lamp comment:location sleeping room
setstate lamp comment:location # deletes the comment
Note:
- You even may set the detailed state (i.e. what you get when you call
list <name;>
by specifying "<time>
<attribute> <value>"
. Take a look at the
savefile
after devices reported values for an example.
shutdown
trigger
trigger <dev> <state>
Trigger a notifyon command.
Example:
sleep
sleep <sec>
Sleep for a given amount, millisecond accuracy.
Example:
sleep 0.5
notifyon btn3 set lamp toggle;;sleep 0.5;;set lamp toggle
Note: As the server is not multithreaded, everything is blocked for
the given amount.
verbose
verbose <level>
Set the verbosity level. Possible values:
- 0 - it will only tell you when the server was started, or stopped
- 1 - it logs all error messages or unknown packets
- 2 - it logs all signals received or sent in a "digested" format,
- 3 - it logs the signals for undefined devices,
- 4 - it logs the TCP/IP connections and the called programs with parameters,
- 5 - is for debugging.
Recommended level is 3 for normal use.
Example:
xmllist
xmllist
Returns an XML tree of all definitions, all notifyon settings and all at
entries. It is not intended for human consumption.
Example:
FHZ> xmllist
<FHZINFO>
<FHZ_DEVICES>
<FHZ name="FHZ" definition="FHZ FHZ" state="fhtbuf: 1c">
<STATE name="fhtbuf" value="23" measured="2006-02-12 14:03:39"/>
<STATE name="serial" value="136e21bc" measured="2006-03-26 08:47:36"/>
[...]
Perl specials
- To use fhz commands from the perl expression, use the function "fhz",
which takes a string argument, this string will be evaluated as an fhz
command chain.
Example:
notifyon piri:on { fhz "set light on" }
-
To make date and time handling easier, before evaluating a perl expression
the variables $sec, $min, $hour, $mday, $month, $year, $wday, $yday, $isdst
are set (see perldoc -f localtime), with the exception that $month is in the
range of 1 to 12, and $year is also corrected by 1900 (as one would normally
expect). Additionally $we is 1 if it is weekend (i.e $wday == 0 ||
$wday == 6), and 0 otherwise.
Example:
notifyon piri:on { if($hour > 18 || $hour < 5) { fhz "set light on" } }
-
Note: do not forget to escape the semicolon (;) with two semicolons
(;;), else your perl code will be interpreted as an fhz command and you
most certainly get syntax errors.
-
The current value (the string you see in paranthesis in the output of the
list command) is available in the
value
hash, to access it,
use $value{<devicename>}
If you need the old value (and time) of the currentliy triggered device,
then you can access it with $oldvalue{$dev}{TIME}
and
$oldvalue{$dev}{VAL}
.
-
To access the numerical value of an FS20 command (e.g. toggle), use the
hash
fs20_c2b. E.g. { Log 2, $fs20_c2b{"toggle"} }
-
If you add the 99_SUNRISE.pm from the contrib directory to your module
directory (NOTE: you have to install the Perl module
DateTime::Event::Sunrise first), then you have access to the follwing
functions:
sunset_rel()
sunset_abs()
sunrise_rel()
sunrise_abs()
isday()
The _rel functions should be used as "at" spec, and the _abs functions as
argument to the on-till argument of the set command.
isday returns 1 if the sun is visible, and 0 else.