From 7ca549809269d9e09e93b6e5882a36cc1afcbaae Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Mon, 18 May 2026 11:50:36 +0300 Subject: [PATCH] add documentation --- Daemons/Readme.md | 14 +- Daemons/deprecated/Readme | 1 + Daemons/domedaemon-astrosib/Readme.md | 205 ++++++++++++++- .../domedaemon-astrosib.creator.user | 2 +- .../domedaemon-astrosib.files | 1 + .../.qtcreator/baader_dome.creator.user | 2 +- Daemons/domedaemon_baader/Readme.md | 219 ++++++++++++++++ Daemons/domedaemon_baader/baader_dome.files | 1 + Daemons/send_coordinates/Readme | 3 +- Daemons/teldaemon_astrosib/Readme.md | 215 +++++++++++++++ Daemons/teldaemon_astrosib/teldaemon.files | 1 + Daemons/weather_database/Readme | 1 + Daemons/weather_proxy/Readme.md | 245 ++++++++++++++++++ Daemons/weather_proxy/weather_proxy.files | 1 + Daemons/weatherdaemon_multimeteo/Readme.md | 50 ++-- README.md | 7 + 16 files changed, 928 insertions(+), 40 deletions(-) create mode 100644 Daemons/deprecated/Readme create mode 100644 Daemons/domedaemon_baader/Readme.md create mode 100644 Daemons/teldaemon_astrosib/Readme.md create mode 100644 Daemons/weather_proxy/Readme.md diff --git a/Daemons/Readme.md b/Daemons/Readme.md index f86efe0..45cfc72 100644 --- a/Daemons/Readme.md +++ b/Daemons/Readme.md @@ -4,15 +4,11 @@ Different daemons & tools - *10micron_stellarium* - simple daemon for 10-micron mount management from stellarium interface - *astrosib* - some scripts used during observations - *deprecated* - deprecated code -- *domedaemon-astrosib* - deprecated astrosib daemon -- *domedaemon_baader* - open/close Baaden dome by network query -- *domedaemon-astrosib* - open/close Astrosib dome by network query -- *netdaemon* - template for net-daemons +- *domedaemon-astrosib* - daemon for "Astrosib" all-sky dome management +- *domedaemon_baader* - daemon for "Baader Planetarium" all-sky dome management - *netsocket* - scripts for management of network 220V-socket - *send_coordinates* - get/send coordinates to 10-micron mount through stellarium daemon (almost deprecated) -- *teldaemon_astrosib* - open/close Astrosib-500 scope covers by network query -- *weatherdaemon* - weather daemon for old meteostation (almost deprecated) -- *weatherdaemon_multimeteo* - (pre-developed) version of weather daemon for ALL sensors on "Astro-M" complex -- *weatherdaemon_newmeteo* - daemon for new (chinese) meteostation (almost deprecated) +- *teldaemon_astrosib* - work with Astrosib-500 scope equipment by network query +- *weatherdaemon_multimeteo* - weather daemon for ALL meteo sensors on "Astro-M" complex - *weather_database* - make database by data of almost deprecated weather daemons -- *weather_proxy* - (pre-developed) daemon gathering meteo data and sharing it on localhost over SHM +- *weather_proxy* - daemon gathering meteo data from `weatherdaemon_multimeteo` and sharing it on localhost over SHM diff --git a/Daemons/deprecated/Readme b/Daemons/deprecated/Readme new file mode 100644 index 0000000..b7689bc --- /dev/null +++ b/Daemons/deprecated/Readme @@ -0,0 +1 @@ +Deprecated (old versions) of daemons; marked for further removal. diff --git a/Daemons/domedaemon-astrosib/Readme.md b/Daemons/domedaemon-astrosib/Readme.md index dac9836..19e8b91 100644 --- a/Daemons/domedaemon-astrosib/Readme.md +++ b/Daemons/domedaemon-astrosib/Readme.md @@ -1,5 +1,204 @@ -New version of "Astrosib" dome daemon. +# domedaemon‑astrosib -Based on snippets_library ver. >= 0.3.2 -Allow more functionality than old one. +**domedaemon‑astrosib** is a daemon that controls an [**Astrosib**](https://astrosib.ru/) all‑sky +dome via a serial line. It provides a TCP/UNIX socket interface for clients, integrates with a +weather proxy to enforce safety rules, and generates a FITS‑style header file with current dome +status. +--- + +## Features + +- **Dome open/close** – fully open or close the dome +- **Stop movement** – immediately stop any ongoing dome motion +- **Independent cover control** – open or close only the northern or southern cover +- **Relay control** – switch three auxiliary relays (power, light, etc.) +- **Status reporting** – cover states, encoder angles, relay states, rain sensor, motor currents, +temperatures +- **Weather integration** – automatically closes the dome and prevents opening when weather is bad +or data is stale +- **Manual override** – via `SIGUSR1` (forbid) / `SIGUSR2` (allow) signals +- **FITS header file** – writes current dome state into a FITS‑style header file (e.g., for later +use by image processing pipelines) +- **Network interface** – supports both INET (TCP) and UNIX domain sockets +- **Daemon mode** – forks, writes PID file, restarts child on crash + +--- + +## Command‑line options + +| Option | Argument | Default | Description | +|----------------------|-------------------|-----------------------------------|-------------------------------------------------------------------| +| `-h`, `--help` | – | – | Show help | +| `-d`, `--device` | *path* | – | Full path to serial device (e.g. `/dev/ttyUSB0`) | +| `-n`, `--node` | *string* | `55555` | Node specification: port number for TCP, or path for UNIX socket | +| `-l`, `--logfile` | *path* | – | Full path to log file | +| `-u`, `--unix` | – | 0 | Use UNIX socket instead of TCP | +| `-v`, `--verbose` | – | 0 | Increase verbosity (each `-v` adds 1 level) | +| `-p`, `--pidfile` | *path* | `/tmp/domedaemon.pid` | PID file path | +| `-H`, `--headerfile` | *path* | `/tmp/dome.fits` | Output file for FITS‑style header | +| `-N`, `--domename` | *name* | `Astrosib` | Dome name inserted into the header | + +--- + +## Socket protocol + +The daemon listens for text‑based commands on the configured socket. Each command returns one or +more lines of output, terminated by newline (`\n`). + +### Commands + +| Command | Description | Example | +|---------------------------------|----------------------------------------------------------------------------|----------------------------------------------| +| `unixt` | Return server’s current UNIX time (seconds with two decimal places) | `unixt` → `unixt=1704067200.12` | +| `status` | Get dome status in old format (four numbers) | `status` → `status=3,3,0,0` | +| `statust` | Get dome status in human‑readable format | `statust` → (see example below) | +| `relay1` … `relay3` | Get/set relay state (0 = off, 1 = on) | `relay1` → `relay1=1` (if queried without argument) | +| `open` | Fully open dome (only if weather permits and observations not forbidden) | `open` | +| `close` | Fully close dome | `close` | +| `stop` | Immediately stop dome movement | `stop` | +| `half1` … `half2` | Get/set state of a single cover (0 = closed, 1 = opened) | `half1 0` | + +Each setter returns an `OK` answer in case of success or error code like `BADVAL` for bad value of +setter. + +### Example `statust` response + +``` +status=3,3,0,0 +operations=permitted +cover1=closed +cover2=closed +angle1=0 +angle2=0 +relay1=0 +relay2=0 +relay3=0 +reqtime=1779087731.049449921 +``` + +- `operations` can be `permitted` or `forbidden` (manual override). +- `cover1` / `cover2` report `closed`, `opened` or `intermediate`. +- `angle1` / `angle2` are encoder values (degrees). +- `relay1` … `relay3` show the current state of each relay. +- `reqtime` is the time when the status was last read from the hardware. + +--- + +## Weather integration + +The daemon retrieves weather data via the **weather_proxy** shared memory interface (`get_weather_data()`). +Safety rules: + +- If `weather.forceoff`, `weather.rain`, or `weather.weather > WEATHER_BAD` → dome is closed and opening is blocked. +- If the weather data is older than **300 seconds** (`WEATHER_LOST`) → treated as lost communication → dome is closed and blocked. +- When weather becomes good again, the daemon automatically resets the `BadWeather` flag and allows normal operation. + +The weather is polled every **5 seconds** (`WEATH_POLL`). + +--- + +## Signal handling + +| Signal | Effect (in child process) | +|----------|------------------------------------------------------| +| `SIGUSR1`| Forbid observations – close dome and block open | +| `SIGUSR2`| Allow observations – remove manual block | +| `SIGTERM`| Stop the daemon and remove PID file | +| `SIGINT` | Same as `SIGTERM` | +| `SIGHUP` | Same as `SIGTERM` | + +--- + +## FITS header file + +The daemon writes a text file (default `/tmp/dome.fits`) with **FITS‑like** keyword/value pairs. +The file is updated every polling cycle (every 5 seconds) and can be used by external pipelines to record dome state. + +Example content: + +``` +DOME = 'Astrosib' / Dome manufacturer/name +DOMESTAT= 'idle' / Dome status +DOMECVR1= 'closed' / Dome cover 1 status +DOMECVR2= 'closed' / Dome cover 2 status +DOMEANG1= 0 / Dome cover 1 angle +DOMEANG2= 0 / Dome cover 2 angle +DOMERLY1= 0 / Dome relay1 state +DOMERLY2= 0 / Dome relay2 state +DOMERLY3= 0 / Dome relay3 state +TDOMMEAS= 1779090474.704 / Measurement time: 2026-05-18 10:47:54 +``` + +The file is created atomically using `mkstemp()` + `rename()`. + +--- + +## Building and dependencies + +### Dependencies + +- [libusefull_macros](https://github.com/eddyem/snippets_library) – common macros and helpers +- [libweather_proxy](https://github.com/eddyem/small_tel/tree/master/Daemons/weather_proxy) – shared memory weather data +- `pthread`, `libc` + +### Build + +```bash +git clone --depth=1 https://github.com/eddyem/small_tel.git +cd small_tel/Daemons/domedaemon-astrosib +mkdir build +cd build +cmake .. +make +``` + +The resulting binary is `domedaemon`. + +### Installation + +Copy the binary to a suitable location (e.g. `/usr/local/bin`) or run `sudo make install`. +It is recommended to run the daemon as a system service (using init script, e.g. in `/etc/local.d/`) +so that it starts automatically at boot. + +--- + +## Usage example + +Start the daemon with a UNIX socket and weather‑aware header: + +```bash +domedaemon -vv -d /dev/ttyS3 -l /var/log/telescope/domedaemon.log +``` + +Connect to the socket using `socat`, `nc` or my [`tty_term`](https://github.com/eddyem/tty_term): + +```bash +nc localhost 55555 +> statust +``` + +Send `SIGUSR1` to forbid observations (e.g. before maintenance): + +```bash +killall -USR1 domedaemon +``` + +--- + +## Notes + +- The serial protocol is specific to Astrosib hardware (commands like `STATUS`, `OPENDOME`, +`CLOSEDOME`, `STOPDOME`, `SHUTTERMOVEDEG`, `SWITCHTOGGILE` are hard‑coded). +- Encoder values are reported as raw integers; interpretation depends on the physical setup. +- The daemon polls the dome every **5 seconds** (`T_INTERVAL`). During that interval it also +processes client requests and checks weather. +- If the serial device becomes unresponsive, the status will return an error and the header will +not be updated. + +--- + +## License + +**GNU General Public License v3.0** or later. +See the `LICENSE` file in repository's root directory or for details. diff --git a/Daemons/domedaemon-astrosib/domedaemon-astrosib.creator.user b/Daemons/domedaemon-astrosib/domedaemon-astrosib.creator.user index 0ad9ba6..42cc270 100644 --- a/Daemons/domedaemon-astrosib/domedaemon-astrosib.creator.user +++ b/Daemons/domedaemon-astrosib/domedaemon-astrosib.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/Daemons/domedaemon-astrosib/domedaemon-astrosib.files b/Daemons/domedaemon-astrosib/domedaemon-astrosib.files index e19b365..f84502f 100644 --- a/Daemons/domedaemon-astrosib/domedaemon-astrosib.files +++ b/Daemons/domedaemon-astrosib/domedaemon-astrosib.files @@ -1,3 +1,4 @@ +Readme.md astrosib_proto.h dome.c dome.h diff --git a/Daemons/domedaemon_baader/.qtcreator/baader_dome.creator.user b/Daemons/domedaemon_baader/.qtcreator/baader_dome.creator.user index 1c48c97..b90a11b 100644 --- a/Daemons/domedaemon_baader/.qtcreator/baader_dome.creator.user +++ b/Daemons/domedaemon_baader/.qtcreator/baader_dome.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/Daemons/domedaemon_baader/Readme.md b/Daemons/domedaemon_baader/Readme.md new file mode 100644 index 0000000..1400fb7 --- /dev/null +++ b/Daemons/domedaemon_baader/Readme.md @@ -0,0 +1,219 @@ +# domedaemon_baader + +**domedaemon_baader** is a daemon that controls a [**Baader +Planetarium**](https://www.baader-planetarium.com/) all‑sky dome via a serial line. It provides a +TCP/UNIX socket interface for clients, integrates with a weather proxy to enforce safety rules, and +generates a FITS‑style header file with current dome status and weather sensor data. + +--- + +## Features + +- **Dome open/close** – fully open or close the dome +- **Stop movement** – immediately stop any ongoing dome motion +- **Weather sensor integration** – reads rain/cloud status from the dome’s internal sensor +- **Error reporting** – reports rain, timeout, and power‑loss error codes +- **Weather proxy integration** – automatically closes the dome and blocks opening when external +weather is bad or data is stale +- **Manual override** – via `SIGUSR1` (forbid) / `SIGUSR2` (allow) signals +- **FITS header file** – writes current dome state and weather sensor status into a FITS‑style +header file (e.g., for later use by image processing pipelines) +- **Network interface** – supports both INET (TCP) and UNIX domain sockets +- **Daemon mode** – forks, writes PID file, restarts child on crash + +--- + +## Command‑line options + +| Option | Argument | Default | Description | +|----------------------|-------------------|---------------------------------|----------------------------------------------------------------------------| +| `-h`, `--help` | – | – | Show help | +| `-d`, `--serialdev` | *path* | – | Full path to serial device (e.g. `/dev/ttyS1`) | +| `-n`, `--node` | *string* | – | Node specification: IP, `name:IP`, or path for UNIX socket. For anonymous UNIX socket use `\0path` or `@path`. | +| `-l`, `--logfile` | *path* | – | Full path to log file | +| `-u`, `--unixsock` | – | 0 | Use UNIX socket instead of INET | +| `-v`, `--verbose` | – | 0 | Increase verbosity (each `-v` adds 1 level; 0: only errors, 1: +warnings, 2: +messages, 3: +debug info) | +| `-p`, `--pidfile` | *path* | `/tmp/domedaemon.pid` | PID file path | +| `-H`, `--headerfile` | *path* | `/tmp/dome.fits` | Output file for FITS‑style header | +| `-N`, `--domename` | *name* | `Baader` | Dome name inserted into the header | +| `-b`, `--baudrate` | *speed* | 9600 | Serial baud rate | +| `-T`, `--sertmout` | *microseconds* | 5000 | Serial read timeout (µs) | +| `-m`, `--maxclients` | *number* | 2 | Maximum number of simultaneously connected clients | + +--- + +## Socket protocol + +The daemon listens for text‑based commands on the configured socket. Each command returns one or +more lines of output, terminated by newline (`\n`). + +### Commands + +| Command | Description | Example | +|---------------------------------|-----------------------------------------------------------------------------|----------------------------------------------| +| `open` | Fully open dome (only if weather permits and observations not forbidden) | `open` | +| `close` | Fully close dome | `close` | +| `stop` | Immediately stop dome movement | `stop` | +| `status` | Get dome status and temperatures | `status` → (see example below) | +| `weather` | Get weather sensor status | `weather` → `weather=good` | +| `dtime` | Return server’s current UNIX time (seconds with milliseconds) | `dtime` → `UNIXT=1704067200.123` | +| `help` | Show available commands (default handler) | `help` | + +Each setter returns an `OK` answer in case of success or error code like `BADVAL` for bad value of +setter. + +### Example `status` response + +``` +status=opened +measuret=1704067200.123 +error=closed@timeout@powerloss +FORBIDDEN +BADWEATHER +errored_command=open +``` + +- `status` can be `opened`, `closed`, `intermediate` or `unknown`. +- `measuret` is the time when the status was last read from the hardware. +- `error` appears when the dome reports an error. It encodes up to three flags: + - `closed` – base error (dome closed due to error) + - `@rain` – rain sensor triggered + - `@timeout` – watchdog timeout + - `@powerloss` – power loss detected +- `FORBIDDEN` appears when observations have been manually disabled (`SIGUSR1`). +- `BADWEATHER` appears when weather proxy reports unsafe conditions. +- `errored_command` shows the last command that failed. + +--- + +## Weather integration + +The daemon retrieves external weather data via the **weather_proxy** shared memory interface +(`get_weather_data()`). +Safety rules: + +- If `weather.forceoff`, `weather.rain`, or `weather.weather > WEATHER_BAD` → dome is closed and opening is blocked. +- If the weather data is older than **300 seconds** (`WEATHER_LOST`) → treated as lost communication → dome is closed and blocked. +- When weather becomes good again, the daemon automatically resets the `BADWEATHER` flag and allows normal operation. + +The weather is polled every **5 seconds** (`T_INTERVAL`). + +--- + +## Dome‑internal weather sensor + +The daemon also reads the dome’s built‑in weather sensor via the `d#ask_wea` command. +Possible states: + +- `0` → `good` (no rain/clouds) +- `1` → `rain/clouds` +- other → `unknown` + +This status is written into the FITS header as `DOMEWEAT`. + +--- + +## Signal handling + +| Signal | Effect (in child process) | +|----------|------------------------------------------------------| +| `SIGUSR1`| Forbid observations – close dome and block open | +| `SIGUSR2`| Allow observations – remove manual block | +| `SIGTERM`| Stop the daemon and remove PID file | +| `SIGINT` | Same as `SIGTERM` | +| `SIGQUIT`| Same as `SIGTERM` | + +--- + +## FITS header file + +The daemon writes a text file (default `/tmp/dome.fits`) with **FITS‑like** keyword/value pairs. +The file is updated every polling cycle (every 5 seconds) and can be used by external pipelines to +record dome state. + +Example content: + +``` +OPERATIO= 'FORBIDDEN' / Observations are forbidden +DOME = 'Baader' / Dome manufacturer/name +DOMESTAT= 'closed' / Dome status +DOMEWEAT= 'good' / Dome weather sensor status +DOMEECOD= 0 / Dome error code: Rain|Watchdog|Power +TDOMMEAS= 1779091627.907 / Measurement time: 2026-05-18 11:07:07 +``` + +The `OPERATIO` keyword appears only when observations are manually forbidden via `SIGUSR1`. + +The file is created atomically using `mkstemp()` + `rename()`. + +--- + +## Building and dependencies + +### Dependencies + +- [libusefull_macros](https://github.com/eddyem/snippets_library) – common macros and helpers +- [libweather_proxy](https://github.com/eddyem/small_tel/tree/master/Daemons/weather_proxy) – shared memory weather data +- `pthread`, `libc` + +### Build + +```bash +git clone --depth=1 https://github.com/eddyem/small_tel.git +cd small_tel/Daemons/domedaemon_baader +make +``` + +The resulting binary is `domedaemon`. + +### Installation + +Copy the binary to a suitable location (e.g. `/usr/local/bin`). +It is recommended to run the daemon as a system service (using init script, e.g. in `/etc/local.d/`) +so that it starts automatically at boot. + +--- + +## Usage example + +Start the daemon with a TCP local-only socket and weather‑aware header: + +```bash +domedaemon -d /dev/ttyS2 -l /var/log/telescope/domedaemon.log -vv \ + -n localhost:55555 -H /tmp/dome.fitsheader +``` + +Connect to the socket using `socat`, `nc` or my [`tty_term`](https://github.com/eddyem/tty_term): + +```bash +nc localhost 55555 +> status +``` + +Send `SIGUSR1` to forbid observations (e.g. before maintenance): + +```bash +killall -USR1 domedaemon +``` + +Don't send signals USR1/USR2 to father process (its PID stored in pidfile): it simply ignores them. +Send them by `killall` to both processes, or by `kill` to daughter process. + +--- + +## Notes + +- The serial protocol is specific to Baader Planetarium hardware. Commands such as `d#opendom`, `d#closdom`, `d#stopdom`, `d#get_dom`, `d#ask_wea`, and `d#warning` are hard‑coded in `commands.h`. +- The dome returns numerical values: + - Position codes: `1111` = fully opened, `2222` = fully closed, anything else = intermediate. + - Weather codes: `0` = good, `1` = rain/clouds, other = unknown. + - Error codes are bit‑encoded: `1` = rain, `10` = timeout, `100` = power loss. +- The daemon polls the dome every **5 seconds** (`T_INTERVAL`). During that interval it also processes client requests and checks external weather. +- If the serial device becomes unresponsive, the status will show `unknown` and the header will not be updated. + +--- + +## License + +**GNU General Public License v3.0** or later. +See the `LICENSE` file in repository's root directory or for details. diff --git a/Daemons/domedaemon_baader/baader_dome.files b/Daemons/domedaemon_baader/baader_dome.files index fcaddd3..b0769e7 100644 --- a/Daemons/domedaemon_baader/baader_dome.files +++ b/Daemons/domedaemon_baader/baader_dome.files @@ -1,3 +1,4 @@ +Readme.md commands.h header.c header.h diff --git a/Daemons/send_coordinates/Readme b/Daemons/send_coordinates/Readme index 0f1b925..e609e07 100644 --- a/Daemons/send_coordinates/Readme +++ b/Daemons/send_coordinates/Readme @@ -1 +1,2 @@ -A simple tool to send/receive coordinates from telescope +A simple tool to send/receive coordinates to/from telescope over `10micron_stellarium` daemon. + diff --git a/Daemons/teldaemon_astrosib/Readme.md b/Daemons/teldaemon_astrosib/Readme.md new file mode 100644 index 0000000..a950110 --- /dev/null +++ b/Daemons/teldaemon_astrosib/Readme.md @@ -0,0 +1,215 @@ +# teldaemon_astrosib + +**teldaemon_astrosib** is a daemon that controls an [**Astrosib**](https://astrosib.ru/) telescope +equipment via a serial line or virtual serial port over TCP. It provides a TCP/UNIX socket +interface for clients, integrates with a +[`weather_proxy`](https://github.com/eddyem/small_tel/tree/master/Daemons/weather_proxy) to enforce +safety rules, and generates a FITS‑header file with current telescope status. + +--- + +## Features + +- **Shutter control** – open / close +- **Focuser control** – absolute move, relative move, stop +- **Cooler control** – switch primary mirror cooler on/off +- **Heater control** – switch secondary mirror heater on/off +- **Status reporting** – shutters state, focuser position, cooler/heater status, mirror and ambient +temperatures +- **Weather integration** – automatically closes shutters and prevents opening when weather is bad +or data is stale +- **Manual override** – via `SIGUSR1` (forbid) / `SIGUSR2` (allow) signals +- **FITS header file** – writes current telescope state into a FITS‑style header file (e.g., for +later use by image processing pipelines) +- **Network interface** – supports both INET (TCP) and UNIX domain sockets +- **Daemon mode** – forks, writes PID file, restarts child on crash + +--- + +## Command‑line options + +| Option | Argument | Default | Description | +|----------------------|-------------------|-----------------------------|-----------------------------------------------------------------------------| +| `-h`, `--help` | – | – | Show help | +| `-v`, `--verbose` | – | 0 | Increase verbosity (each `-v` adds 1 level) | +| `-l`, `--logfile` | *path* | – | Full path to log file (otherwise stderr) | +| `-n`, `--node` | *string* | – | Node specification: IP, `name:IP`, or path for UNIX socket. For anonymous UNIX socket use `\0path` or `@path`. | +| `-u`, `--unixsock` | – | 0 | Use UNIX socket instead of INET | +| `-m`, `--maxclients` | *number* | 2 | Maximum number of simultaneously connected clients | +| `-p`, `--pidfile` | *path* | `/tmp/teldaemon.pid` | PID file path | +| `-d`, `--serialdev` | *path* | – | Full path to serial device (e.g. `/dev/ttyUSB0`) | +| `-b`, `--baudrate` | *speed* | 9600 | Serial baud rate | +| `-t`, `--sertmout` | *microseconds* | 1000000 (1 sec) | Serial read timeout (µs) | +| `-H`, `--headerfile` | *path* | `/tmp/telescope.fits` | Output file for FITS‑style header | +| `-N`, `--telname` | *name* | `Astro-M (1)` | Telescope name inserted into the header | +| `-M`, `--headermask` | *bitmask* | `0xff` (all bits set) | Mask controlling which information appears in the header. Use `-1` to list bits. | + +### Header mask bits (used with `-M`) + +| Bit | Description | +|-----|--------------------------| +| 0 | telescope name | +| 1 | focuser status | +| 2 | cooler status | +| 3 | heater status | +| 4 | external temperature | +| 5 | mirror temperature | +| 6 | measurement time | + +For example, if you are using an external focuser and want to prevent the possibility of its data +being overwritten by the telescope data, use a mask `-M125` (alternatively: `-M0x7D` or `-M0b1111101`). + +--- + +## Socket protocol + +The daemon listens for text‑based commands on the configured socket. Each command returns one or +more lines of output, terminated by newline (`\n`). + +### Commands + +| Command | Description | Example | +|---------------------------------|-----------------------------------------------------------------------------|-----------------------------------| +| `focrel ` | Move focuser relatively (negative = inward, positive = outward) | `focrel = -500` | +| `focabs ` | Move focuser to absolute position (0 … 65000) | `focabs = 32000` | +| `focpos` | Get current focuser position | `focpos` → `focpos=12345` | +| `open` | Open shutters (only if weather permits and observations not forbidden) | `open` | +| `close` | Close shutters | `close` | +| `status` | Get shutters state, temperatures, last error, and safety flags | `status` → (see example below) | +| `focstop` | Immediately stop focuser movement | `focstop` | +| `cooler <0/1>` | Switch primary mirror cooler off (0) or on (1) | `cooler = 1` | +| `heater <0/1>` | Switch secondary mirror heater off (0) or on (1) | `heater = 0` | +| `dtime` | Return server’s current UNIX time (seconds with milliseconds) | `dtime` → `UNIXT=1704067200.123` | +| `help` | Show available commands (default handler) | `help` | + +Each setter returns an `OK` answer in case of success or error code like `BADVAL` for bad value of setter. + +### Example `status` response + +``` +status=closed +measuret=1779086249.480 +mirrortemp=6.2 +ambienttemp=6.3 +``` + +- `status` can be `opened`, `closed`, `intermediate` or `unknown`. +- `measuret` is the time when the status was last read from the hardware. +- `errored_command` appears if the last attempted command failed. +- `FORBIDDEN` appears when observations have been manually disabled (`SIGUSR1`). +- `BADWEATHER` appears when weather proxy reports unsafe conditions. + +--- + +## Weather integration + +The daemon retrieves weather data via the **weather_proxy** shared memory interface (`get_weather_data()`). +Safety rules: + +- If `weather.forceoff`, `weather.rain`, or `weather.weather > WEATHER_TERRIBLE` → shutters are closed and opening is blocked. +- If the weather data is older than **900 seconds** (`WEATHER_LOST`) → treated as lost communication → shutters are closed and blocked. +- When weather becomes good again, the daemon automatically resets the `BADWEATHER` flag and allows normal operation. + +--- + +## Signal handling + +| Signal | Effect (in child process) | +|----------|------------------------------------------------------| +| `SIGUSR1`| Forbid observations – close shutters and block open | +| `SIGUSR2`| Allow observations – remove manual block | +| `SIGTERM`| Stop the daemon and remove PID file | +| `SIGINT` | Same as `SIGTERM` | + +--- + +## FITS header file + +The daemon writes a text file (default `/tmp/telescope.fits`) with **FITS‑like** keyword/value +pairs. The file is updated every polling cycle (every 2 seconds) and can be used by external +pipelines to record telescope state. + +Example content: + +``` +TELESCOP= 'Astro-M (1)' / Telescope name +TELSTAT = 'closed' / Telescope shutters' status +TELCOOLR= 0 / Primary mirror cooler status: 0/1 (off/on) +TELHEATR= 0 / Secondary mirror heater status: 0/1 (off/on) +TDOME = 6.3 / In-dome temperature, degC +TMIRROR = 6.0 / Mirror temperature, degC +TTELMEAS= 1779086301.494 / Measurement time: 2026-05-18 09:38:21 +``` + +The file is created atomically using `mkstemp()` + `rename()`. + +--- + +## Building and dependencies + +### Dependencies + +- [libusefull_macros](https://github.com/eddyem/snippets_library) – common macros and helpers +- [libweather_proxy](https://github.com/eddyem/weather_proxy) – shared memory weather data +- `pthread`, `libc` + +### Build + +```bash +git clone --depth=1 https://github.com/eddyem/small_tel.git +cd small_tel/Daemons/teldaemon_astrosib +make +``` + +The resulting binary is `teldaemon_astrosib`. + +### Installation + +Copy the binary to a suitable location (e.g. `/usr/local/bin`). +It is recommended to run the daemon as a system service (using init script, e.g. in `/etc/local.d/`) +so that it starts automatically at boot. + +--- + +## Usage example + +Start the daemon with a UNIX socket and weather‑aware header: + +```bash +teldaemon_astrosib -u -n "/var/run/teldaemon.sock" \ + -d /dev/ttyUSB0 -b 115200 \ + -H /var/state/telescope.fits \ + -N "Astrosib-500" -M 0x7f +``` + +Connect to the socket using `socat`, `nc` or my [`tty_term`](https://github.com/eddyem/tty_term): + +```bash +socat UNIX-CONNECT:/var/run/teldaemon.sock - +> status +``` + +Send `SIGUSR1` to forbid observations (e.g. before maintenance): + +```bash +kill -USR1 $(cat /tmp/teldaemon.pid) +``` + +--- + +## Notes + +- The serial protocol is specific to Astrosib hardware (commands like `FOCUSERGO?`, +`SHUTTEROPEN?1,1,1,1,1`, etc. are hard‑coded). +- Focuser absolute position range is **0 … 65000** (values outside this range are ignored). +- The daemon polls the telescope every **2 seconds** (`T_INTERVAL`). During that interval it also +processes client requests and checks weather. +- If the serial device becomes unresponsive, the status will show `unknown` and the header will not +be updated. + +--- + +## License + +**GNU General Public License v3.0** or later. +See the `LICENSE` file in repository's root directory or for details. diff --git a/Daemons/teldaemon_astrosib/teldaemon.files b/Daemons/teldaemon_astrosib/teldaemon.files index fcaddd3..b0769e7 100644 --- a/Daemons/teldaemon_astrosib/teldaemon.files +++ b/Daemons/teldaemon_astrosib/teldaemon.files @@ -1,3 +1,4 @@ +Readme.md commands.h header.c header.h diff --git a/Daemons/weather_database/Readme b/Daemons/weather_database/Readme index 33db087..dfca59a 100644 --- a/Daemons/weather_database/Readme +++ b/Daemons/weather_database/Readme @@ -1,4 +1,5 @@ Collect weather data from new meteostation in sqlite3 database. +// This is old version and need to be modificated for working with modern weather daemon) Parameters: diff --git a/Daemons/weather_proxy/Readme.md b/Daemons/weather_proxy/Readme.md new file mode 100644 index 0000000..590ec4f --- /dev/null +++ b/Daemons/weather_proxy/Readme.md @@ -0,0 +1,245 @@ +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 command‑line 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 [-u] [-l ] [-p ] [-f ] [-v] +``` + +#### Options + +| Option | Description | +|--------|-------------| +| `-n ` | Connection endpoint. For TCP: `host:port`. For UNIX sockets: path to socket. Required. | +| `-u` | Use a UNIX socket instead of TCP. | +| `-l ` | Write log messages to the specified file. | +| `-p ` | PID file (default `/tmp/weather_proxy.pid`). | +| `-f ` | Save the latest weather data as a FITS‑header 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 power‑off 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 + +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`. + +## FITS‑Header Output + +If the `-f ` 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 plain‑text 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. diff --git a/Daemons/weather_proxy/weather_proxy.files b/Daemons/weather_proxy/weather_proxy.files index 809b8ac..101731d 100644 --- a/Daemons/weather_proxy/weather_proxy.files +++ b/Daemons/weather_proxy/weather_proxy.files @@ -1,3 +1,4 @@ +Readme.md weather_client.c weather_clt_example.c weather_daemon.c diff --git a/Daemons/weatherdaemon_multimeteo/Readme.md b/Daemons/weatherdaemon_multimeteo/Readme.md index 8ea6560..71b8b9f 100644 --- a/Daemons/weatherdaemon_multimeteo/Readme.md +++ b/Daemons/weatherdaemon_multimeteo/Readme.md @@ -44,14 +44,14 @@ emerge net-analyzer/net-snmp ``` Available plugin options: - - `DUMMY`  Dummy weather station for testing. - - `FDEXAMPLE`  Example file descriptor plugin. - - `HYDREON`  Hydreon RG-11 rain sensor. - - `BTAMETEO`  BTA 6-m telescope main meteostation (shared memory). - - `REINHARDT`  Old Reinhardt meteostation. - - `WXA100`  Vaisala WXA100 ultrasonic station. - - `SNMP`  UPS monitoring via SNMP. - - `LIGHTNING`  AS3935-based lightning sensor. + - `DUMMY` — Dummy weather station for testing. + - `FDEXAMPLE` — Example file descriptor plugin. + - `HYDREON` — Hydreon RG-11 rain sensor. + - `BTAMETEO` — BTA 6-m telescope main meteostation (shared memory). + - `REINHARDT` — Old Reinhardt meteostation. + - `WXA100` — Vaisala WXA100 ultrasonic station. + - `SNMP` — UPS monitoring via SNMP. + - `LIGHTNING` — AS3935-based lightning sensor. 4. Building: @@ -94,7 +94,7 @@ Format: ``` - `library`: path to the shared library, e.g. `libwxa100.so`. -- `type`: Connection type  `D` for serial device, `U` for UNIX socket, `N` for INET socket. +- `type`: Connection type — `D` for serial device, `U` for UNIX socket, `N` for INET socket. - `parameter`: device path and optional speed (`/dev/ttyS0:9600`), UNIX socket name, or `host:port` for INET. Examples: @@ -150,7 +150,7 @@ Run with: superweatherdaemon -c /etc/weather.conf ``` -To run on system start you can use OpenRó `rc.local` mechanism. +To run on system start you can use OpenRС `rc.local` mechanism. ## Plugins @@ -185,8 +185,8 @@ daemon will try to reconnect every `reinit_delay` seconds. | Library | Sensor | Type | |---------|--------|------| -| `libwsdummy.so` | Dummy station  outputs random walk data around realistic values. | Test / Development | -| `libfdex.so` | Example of a filedescriptor based plugin. Prompts for commaseparated values. | Example | +| `libwsdummy.so` | Dummy station — outputs random walk data around realistic values. | Test / Development | +| `libfdex.so` | Example of a file—descriptor based plugin. Prompts for comma—separated values. | Example | | `libhydreon.so` | Hydreon RG-11 optical rain sensor. | Serial | | `libbtameteo.so` | BTA 6-m telescope main meteostation (shared memory). | Shared Memory | | `libreinhardt.so` | Old Reinhardt meteostation (serial, `?U` command). | Serial | @@ -216,22 +216,22 @@ Use the existing plugins as templates. A minimal plugin must: The daemon combines data from all active plugins and continuously evaluates a global **weather level**: -- `0`  **GOOD**: observations can start safely. -- `1`  **BAD**: risky to start, but can continue. -- `2`  **TERRIBLE**: dome must close, instruments park. -- `3`  **PROHIBITED**: complete shutdown, power off equipment. +- `0` — **GOOD**: observations can start safely. +- `1` — **BAD**: risky to start, but can continue. +- `2` — **TERRIBLE**: dome must close, instruments park. +- `3` — **PROHIBITED**: complete shutdown, power off equipment. ### Criteria Each weather parameter (wind speed, humidity, clouds, sky temperature, lightning distance, precipitation, etc.) has configurable thresholds: -- `good`  below/above this (depending on sign) the condition is good. -- `bad`  above this the condition is bad. -- `terrible`  above this the condition is terrible. -- `prohibited`  (if defined) above this the condition goes directly to PROHIBITED. -- `negflag`  if `1`, a smaller value is worse (e.g., clouds). -- `shtdnflag`  if `1`, entering the terrible/prohibited range also sets the **FORCE SHUTDOWN** flag. +- `good` — below/above this (depending on sign) the condition is good. +- `bad` — above this the condition is bad. +- `terrible` — above this the condition is terrible. +- `prohibited` — (if defined) above this the condition goes directly to PROHIBITED. +- `negflag` — if `1`, a smaller value is worse (e.g., clouds). +- `shtdnflag` — if `1`, entering the terrible/prohibited range also sets the **FORCE SHUTDOWN** flag. ### Special Flags @@ -251,9 +251,9 @@ passed since the last serious event. This prevents rapid toggling. The daemon listens on two interfaces: -1. **Network socket** (TCP, default port 12345)  read-only (in meaning they cannot change any +1. **Network socket** (TCP, default port 12345) — read-only (in meaning they cannot change any parameters) access for remote clients. -2. **Local UNIX socket** (abstract or filesystem, default `@weather`)  full control for local applications. +2. **Local UNIX socket** (abstract or filesystem, default `@weather`) — full control for local applications. Commands are sent as plain text strings, terminated by a newline. @@ -285,7 +285,7 @@ Commands are sent as plain text strings, terminated by a newline. Reply format: each line is a FITS-like `KEY = value / comment` string; commands that set something usually echo back the variable and its new value. For `get=` each `KEY` have a suffix in square -brackets  number of plugin, e.g. `WIND[1]= 10.1 / Wind speed, m/s`. +brackets — number of plugin, e.g. `WIND[1]= 10.1 / Wind speed, m/s`. ## Signals diff --git a/README.md b/README.md index 20fa37a..008324c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # small_tel + Different utilities for small telescopes + +## Directories: + +- Auxiliary_utils - some frequently used over observations utils and scripts +- Daemons - main daemons (weather, dome, telescope equipment, mount) +- Docs - some documentation (Russian)