Modular Computers the manual GitHub

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.

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

Download weather-log.lua

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

Download weather-roof.lua

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.