Weather Sensor
A weather sensor tells the weather where its block is, and raises an event when it changes.
Facts
| | |
|—|—|
| Type | weather |
| Address | An expansion slot path such as exp:0, or a hub’s |
| Interrupt | Raised while events wait |
| Power | Nothing to speak of; it works while a running computer powers it |
| Info | kind (weather_sensor) |
The weather is one of clear, rain, snow or thunder. It is worked out for the sensor’s block
once a second, from the world’s weather and the biome there: a block in a desert reads clear even
while it rains elsewhere, and a cold biome reads snow. The sensor does not need to see the sky.
In mcos
/dev/weather0 (weather1 for the next) is a read-only file, an event a line: the new weather.
rain
A read with nothing waiting waits for the next change, and poll reports the file readable (IN)
while one waits. When events were dropped, a line lost n comes before the next one. The first
look at the weather is not a change. Opening it to write fails with EACCES.
cat /dev/weather0 # waits, then prints each change
The file’s ioctls are the sensor’s methods, by name, in any open mode. The weather now, without
waiting for a change, is getWeather:
local now = sys.ioctl(fd, "getWeather") -- "clear", "rain", "snow" or "thunder"
A sensor that is gone answers ENODEV. setLabel labels it, as for any device (see
The sys library). The file and pull take from the same buffer, in order (a change
read from one is gone from the other); polling loses nothing, so a program can wait with sys.poll
and then pull.
Methods
getWeather() → string
The weather now: clear, rain, snow or thunder. clear before its first look.
pull() → event or nil
The oldest change waiting, as an event table (see Events), or nil when none waits. Each is taken once.
Events
| Field | Value |
|---|---|
name |
"weather" |
old |
the weather before |
new |
the weather now |
lost |
present when events were dropped: how many |
Each change raises the sensor’s interrupt, which stays raised while any wait. At most 32 wait. Events are kept across a save, and the weather the sensor saw last is kept too, so a load is not a change. Events are dropped while no program runs.
Examples
Run these with lua name.lua &, from a computer with a weather sensor. For why they loop without
yielding, see Writing programs.
Print each change
local f = io.open("/dev/weather0")
while true do
print("the weather is now " .. f:read("l")) -- waits for the next change
end
A weather diary
-- Keep a diary of the weather: each change the weather sensor reports is appended to a log with the
-- world's time ("Day 4 11:20:00 rain"), so `cat /home/weather.log` shows a world's history.
--
-- It reads the sensor's file, a line a change: read blocks until the weather changes, which may be
-- a long while. A first line notes the weather when the program started (the sensor's getWeather,
-- through its file's ioctl), since that is not a change.
local sys = require("sys")
local LOG = "/home/weather.log"
local sensor = assert(io.open("/dev/weather0"))
local function note(text)
local log = assert(io.open(LOG, "a"))
log:write(os.date("%c"), " ", text, "\n")
log:close() -- (on the disk at once)
end
note(sys.ioctl(sys.fileno(sensor), "getWeather") .. " (started)")
for line in sensor:lines() do
note(line) -- "rain", or "lost n" when changes were dropped
end
A roof that closes in the rain
-- Close the roof while it rains: a sticky piston on the redstone card's up face pushes a roof
-- block over a crop field, or a skylight, while the weather sensor says rain, snow or thunder,
-- and pulls it back when it clears.
--
-- It asks the sensor for the weather now with its method, getWeather (an ioctl on its file), then
-- reads the file for each change: read blocks until the weather changes.
local sys = require("sys")
local ROOF = "up"
local WET = {rain = true, snow = true, thunder = true}
local sensor = assert(io.open("/dev/weather0"))
local card = assert(sys.open("/dev/redstone0"))
local function roof(weather)
sys.ioctl(card, "set", {[ROOF] = {powered = WET[weather] and 15 or 0}})
end
roof(sys.ioctl(sys.fileno(sensor), "getWeather"))
for weather in sensor:lines() do
if not weather:find("^lost ") then -- (a "lost n" line: the change after it says the weather)
roof(weather)
end
end
It needs a redstone card in the same computer, and a sticky piston on
its top face. getWeather gives the weather at the start, so a program started in the rain closes
the roof at once.