Files
small_tel/Daemons/weather_proxy/Readme.md
2026-05-18 11:50:36 +03:00

246 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
The `weather_proxy` package offers a lightweight daemon (`weather_proxy`) that receives data from
[`supermeteodaemon`](https://github.com/eddyem/small_tel/tree/master/Daemons/weatherdaemon_multimeteo)
via a TCP or UNIX socket, parses it, and makes it available locally through a
shared memory segment. A client library (`libweather.so`) and a simple command-line utility
(`chkweather`) are also provided to easily retrieve and check weather conditions.
---
## Overview
The main daemon (`weather_proxy`) connects to a running `supermeteodaemon` process, parses the
incoming FITS-header-style data stream, and regularly updates a POSIX shared memory segment
(`/weather_shm`). A named semaphore (`/weather_sem`) protects the shared data. The client library
offers the `get_weather_data()` function to read this shared memory and return the data in a
`weather_data_t` structure. The `chkweather` utility uses this function to quickly check the
current weather status and produce an exit code suitable for scripting.
## Components
The project consists of the following source files:
| File | Description |
|------|-------------|
| `weather_daemon.c` | The main proxy daemon. |
| `weather_client.c` | The client library (`libweather.so`) with `get_weather_data()`. |
| `weather_data.h` | Common data structure and definitions. |
| `chkweather.c` | A simple commandline tool to check weather status. |
| `weather_clt_example.c` | Example usage of the client library. |
| `Makefile` | Builds the daemon, client library, and utilities. |
## Building
The package requires a C compiler (e.g., `gcc`) and the [`usefull_macros` library](https://github.com/eddyem/snippets_library).
To install the latter clone its code and use `cmake`/`make`:
```bash
git clone --depth=1 https://github.com/eddyem/snippets_library
cd snippets_library
mkdir build
cd build
cmake ..
make
su -c "make install"
# or "sudo make install" if you have "sudo" configured
```
Then build the project:
```bash
make
```
This produces:
- `weather_proxy` the main daemon
- `libweather.so` the shared client library
- `chkweather` the weather check utility
- `weather_clt_example` an example client
To install:
```bash
su -c "make install"
```
This copies `libweather.so` to `/usr/local/lib`, installs `weather_data.h` in `/usr/local/include`,
and places the executables in `/usr/local/bin`.
## Usage
### Running the proxy daemon (`weather_proxy`)
```bash
weather_proxy -n <node> [-u] [-l <logfile>] [-p <pidfile>] [-f <fitsheader>] [-v]
```
#### Options
| Option | Description |
|--------|-------------|
| `-n <node>` | Connection endpoint. For TCP: `host:port`. For UNIX sockets: path to socket. Required. |
| `-u` | Use a UNIX socket instead of TCP. |
| `-l <file>` | Write log messages to the specified file. |
| `-p <file>` | PID file (default `/tmp/weather_proxy.pid`). |
| `-f <file>` | Save the latest weather data as a FITSheader file. |
| `-v` | Increase verbosity (can be used multiple times). |
#### Example
Connect to `supermeteodaemon` on TCP port 12345 at `localhost`:
```bash
weather_proxy -n localhost:12345 -v -l /var/log/weather_proxy.log
```
Use a UNIX socket and store the FITS header:
```bash
weather_proxy -n /tmp/superweather.sock -u -f /tmp/latest_weather.header
```
### Checking weather (`chkweather`)
`chkweather` reads the shared memory and prints the current weather data. It returns an exit code
according to the weather condition:
| Exit Code | Meaning |
|-----------|---------|
| `0` | Weather is good observations may start. |
| `1` | Weather is bad cannot start, but ongoing observations may continue. |
| `2` | Weather is terrible close the dome, park. |
| `3` | Weather is prohibited power off equipment, prepare to shut down the computer (or data is too old). |
Example:
```bash
if ./chkweather; then
echo "Conditions are good - starting observations"
else
echo "Bad weather - stopping"
fi
```
### Using the client library in your own code
The library provides a single function:
```c
#include "weather_data.h"
int get_weather_data(weather_data_t *data);
```
It fills the `weather_data_t` structure with the latest weather information. Returns `0` on
success, `-1` on failure.
#### `weather_data_t` structure
```c
typedef struct {
weather_condition_t weather; // condition (0..3)
float windmax; // max wind in last hour (m/s)
float wind; // current wind speed (m/s)
float clouds; // sky "quality" (>2500 = good)
float exttemp; // external temperature (°C)
float pressure; // atmospheric pressure (mmHg)
float humidity; // relative humidity (%)
int rain; // 1 if rain is detected
int forceoff; // forced poweroff flag
time_t last_update; // timestamp of the data
} weather_data_t;
```
The `weather_condition_t` enum:
| Value | Meaning |
|-------|---------|
| `WEATHER_GOOD` (0) | Clear for observations |
| `WEATHER_BAD` (1) | Unfavourable but not critical |
| `WEATHER_TERRIBLE` (2) | Dangerous conditions close and park |
| `WEATHER_PROHIBITED` (3) | Emergency close, park and prepare for powering off |
Example client:
```c
#include "weather_data.h"
#include <stdio.h>
int main() {
weather_data_t wd;
if (get_weather_data(&wd) == 0) {
printf("Weather: %d, Temp: %.1f C\n", wd.weather, wd.exttemp);
}
return 0;
}
```
Compile with:
```bash
gcc -o myclient myclient.c -lweather
```
## Data Flow
1. **supermeteodaemon** collects data from various sensors and outputs it as lines of `KEY=VALUE`
pairs (FITS-header style).
2. **weather_proxy** connects to the socket, sends a `"get\n"` command, and parses the incoming
lines.
3. It extracts the fields: `WEATHER`, `WINDMAX1`, `PRECIP`, `CLOUDS`, `WIND`, `EXTTEMP`,
`PRESSURE`, `HUMIDITY`, `FORCEOFF`, and `TMEAS` (the timestamp).
4. The data is stored in a POSIX shared memory segment (`/weather_shm`) and is protected by a named
semaphore (`/weather_sem`).
5. Client applications (like `chkweather` or your own code) use `get_weather_data()` to read the
shared memory safely.
## Signals
The daemon responds to:
- **SIGUSR1** Forbid observations (sets an internal `forbidden` flag which overrides the current
weather to `WEATHER_PROHIBITED`).
- **SIGUSR2** Permit observations (clears the `forbidden` flag).
These signals are only handled by the worker child process; the parent monitor process ignores
them. So you can send them simply by `killall -sUSR1 weather_proxy`.
## FITSHeader Output
If the `-f <file>` option is given, the daemon writes each received `KEY=VALUE` line to a temporary
file and, when the data set is complete (i.e., the `TWEATH` line is received), it atomically
replaces the target file. This produces a plaintext file that can be used as a FITS header or for
other applications.
Example generated file:
```
WIND = 4.30 / Wind, m/s
WINDMAX = 5.90 / Maximal wind speed for last 24 hours
WINDMAX1= 5.90 / Maximal wind speed for last hour
WINDDIR = 32.75 / Wind direction, degr (CW from north to FROM)
WINDDIR1= 25.97 / Mean wind speed direction for last hour
WINDDIR2= 35.37 / Mean wind speed^2 direction for last hour
HUMIDITY= 57.50 / Humidity, percent
EXTTEMP = 9.00 / Ambient temperature, degC
PRESSURE= 585.72 / Atmospheric pressure, mmHg
PRECIP = 0 / Precipitation (1 - yes, 0 - no)
PRECIPLV= 0.00 / Cumulative precipitation level (mm)
CLOUDS = 2399.50 / Integral sky quality value (bigger - better)
WEATHER = 0 / Weather (0..3: good/bad/terrible/prohibited)
TSINCERN= 20 / Minutes since rain (20 means a lot of)
RAINPOW = 0 / Rain strength, 0..255
RAINAVG = 0 / Average rain strength, 0..255
RSAMBL = 48 / Ambient light by rain sensor, 0..255
RSFREEZ = 0 / Rain sensor is freezed
TWEATH = 1779085104 / Last weather time: 2026-05-18 09:18:24
```
----
## License
Copyright © 2026 Edward V. Emelianov.
**GNU General Public License v3.0** or later.
See the `LICENSE` file in repository's root directory or [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/)
for details.