mirror of
https://github.com/eddyem/small_tel.git
synced 2026-06-19 02:16:23 +03:00
add documentation
This commit is contained in:
@@ -4,15 +4,11 @@ Different daemons & tools
|
|||||||
- *10micron_stellarium* - simple daemon for 10-micron mount management from stellarium interface
|
- *10micron_stellarium* - simple daemon for 10-micron mount management from stellarium interface
|
||||||
- *astrosib* - some scripts used during observations
|
- *astrosib* - some scripts used during observations
|
||||||
- *deprecated* - deprecated code
|
- *deprecated* - deprecated code
|
||||||
- *domedaemon-astrosib* - deprecated astrosib daemon
|
- *domedaemon-astrosib* - daemon for "Astrosib" all-sky dome management
|
||||||
- *domedaemon_baader* - open/close Baaden dome by network query
|
- *domedaemon_baader* - daemon for "Baader Planetarium" all-sky dome management
|
||||||
- *domedaemon-astrosib* - open/close Astrosib dome by network query
|
|
||||||
- *netdaemon* - template for net-daemons
|
|
||||||
- *netsocket* - scripts for management of network 220V-socket
|
- *netsocket* - scripts for management of network 220V-socket
|
||||||
- *send_coordinates* - get/send coordinates to 10-micron mount through stellarium daemon (almost deprecated)
|
- *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
|
- *teldaemon_astrosib* - work with Astrosib-500 scope equipment by network query
|
||||||
- *weatherdaemon* - weather daemon for old meteostation (almost deprecated)
|
- *weatherdaemon_multimeteo* - weather daemon for ALL meteo sensors on "Astro-M" complex
|
||||||
- *weatherdaemon_multimeteo* - (pre-developed) version of weather daemon for ALL sensors on "Astro-M" complex
|
|
||||||
- *weatherdaemon_newmeteo* - daemon for new (chinese) meteostation (almost deprecated)
|
|
||||||
- *weather_database* - make database by data of almost deprecated weather daemons
|
- *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
|
||||||
|
|||||||
1
Daemons/deprecated/Readme
Normal file
1
Daemons/deprecated/Readme
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Deprecated (old versions) of daemons; marked for further removal.
|
||||||
@@ -1,5 +1,204 @@
|
|||||||
New version of "Astrosib" dome daemon.
|
# domedaemon‑astrosib
|
||||||
|
|
||||||
Based on snippets_library ver. >= 0.3.2
|
**domedaemon‑astrosib** is a daemon that controls an [**Astrosib**](https://astrosib.ru/) all‑sky
|
||||||
Allow more functionality than old one.
|
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 <http://www.gnu.org/licenses/> for details.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 19.0.1, 2026-05-15T14:43:04. -->
|
<!-- Written by QtCreator 19.0.1, 2026-05-18T10:54:40. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
Readme.md
|
||||||
astrosib_proto.h
|
astrosib_proto.h
|
||||||
dome.c
|
dome.c
|
||||||
dome.h
|
dome.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 19.0.1, 2026-05-15T14:02:48. -->
|
<!-- Written by QtCreator 19.0.1, 2026-05-18T11:16:57. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
219
Daemons/domedaemon_baader/Readme.md
Normal file
219
Daemons/domedaemon_baader/Readme.md
Normal file
@@ -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 <http://www.gnu.org/licenses/> for details.
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
Readme.md
|
||||||
commands.h
|
commands.h
|
||||||
header.c
|
header.c
|
||||||
header.h
|
header.h
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
215
Daemons/teldaemon_astrosib/Readme.md
Normal file
215
Daemons/teldaemon_astrosib/Readme.md
Normal file
@@ -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 <steps>` | Move focuser relatively (negative = inward, positive = outward) | `focrel = -500` |
|
||||||
|
| `focabs <position>` | 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 <http://www.gnu.org/licenses/> for details.
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
Readme.md
|
||||||
commands.h
|
commands.h
|
||||||
header.c
|
header.c
|
||||||
header.h
|
header.h
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Collect weather data from new meteostation in sqlite3 database.
|
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:
|
Parameters:
|
||||||
|
|
||||||
|
|||||||
245
Daemons/weather_proxy/Readme.md
Normal file
245
Daemons/weather_proxy/Readme.md
Normal file
@@ -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 <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 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 <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`.
|
||||||
|
|
||||||
|
## FITS‑Header 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 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.
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
Readme.md
|
||||||
weather_client.c
|
weather_client.c
|
||||||
weather_clt_example.c
|
weather_clt_example.c
|
||||||
weather_daemon.c
|
weather_daemon.c
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ emerge net-analyzer/net-snmp
|
|||||||
```
|
```
|
||||||
|
|
||||||
Available plugin options:
|
Available plugin options:
|
||||||
- `DUMMY` Dummy weather station for testing.
|
- `DUMMY` — Dummy weather station for testing.
|
||||||
- `FDEXAMPLE` Example file descriptor plugin.
|
- `FDEXAMPLE` — Example file descriptor plugin.
|
||||||
- `HYDREON` Hydreon RG-11 rain sensor.
|
- `HYDREON` — Hydreon RG-11 rain sensor.
|
||||||
- `BTAMETEO` BTA 6-m telescope main meteostation (shared memory).
|
- `BTAMETEO` — BTA 6-m telescope main meteostation (shared memory).
|
||||||
- `REINHARDT` Old Reinhardt meteostation.
|
- `REINHARDT` — Old Reinhardt meteostation.
|
||||||
- `WXA100` Vaisala WXA100 ultrasonic station.
|
- `WXA100` — Vaisala WXA100 ultrasonic station.
|
||||||
- `SNMP` UPS monitoring via SNMP.
|
- `SNMP` — UPS monitoring via SNMP.
|
||||||
- `LIGHTNING` AS3935-based lightning sensor.
|
- `LIGHTNING` — AS3935-based lightning sensor.
|
||||||
|
|
||||||
4. Building:
|
4. Building:
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ Format:
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `library`: path to the shared library, e.g. `libwxa100.so`.
|
- `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.
|
- `parameter`: device path and optional speed (`/dev/ttyS0:9600`), UNIX socket name, or `host:port` for INET.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -150,7 +150,7 @@ Run with:
|
|||||||
superweatherdaemon -c /etc/weather.conf
|
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
|
## Plugins
|
||||||
|
|
||||||
@@ -185,8 +185,8 @@ daemon will try to reconnect every `reinit_delay` seconds.
|
|||||||
|
|
||||||
| Library | Sensor | Type |
|
| Library | Sensor | Type |
|
||||||
|---------|--------|------|
|
|---------|--------|------|
|
||||||
| `libwsdummy.so` | Dummy station outputs random walk data around realistic values. | Test / Development |
|
| `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 |
|
| `libfdex.so` | Example of a file—descriptor based plugin. Prompts for comma—separated values. | Example |
|
||||||
| `libhydreon.so` | Hydreon RG-11 optical rain sensor. | Serial |
|
| `libhydreon.so` | Hydreon RG-11 optical rain sensor. | Serial |
|
||||||
| `libbtameteo.so` | BTA 6-m telescope main meteostation (shared memory). | Shared Memory |
|
| `libbtameteo.so` | BTA 6-m telescope main meteostation (shared memory). | Shared Memory |
|
||||||
| `libreinhardt.so` | Old Reinhardt meteostation (serial, `?U` command). | Serial |
|
| `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
|
The daemon combines data from all active plugins and continuously evaluates a global **weather
|
||||||
level**:
|
level**:
|
||||||
|
|
||||||
- `0` **GOOD**: observations can start safely.
|
- `0` — **GOOD**: observations can start safely.
|
||||||
- `1` **BAD**: risky to start, but can continue.
|
- `1` — **BAD**: risky to start, but can continue.
|
||||||
- `2` **TERRIBLE**: dome must close, instruments park.
|
- `2` — **TERRIBLE**: dome must close, instruments park.
|
||||||
- `3` **PROHIBITED**: complete shutdown, power off equipment.
|
- `3` — **PROHIBITED**: complete shutdown, power off equipment.
|
||||||
|
|
||||||
### Criteria
|
### Criteria
|
||||||
|
|
||||||
Each weather parameter (wind speed, humidity, clouds, sky temperature, lightning distance,
|
Each weather parameter (wind speed, humidity, clouds, sky temperature, lightning distance,
|
||||||
precipitation, etc.) has configurable thresholds:
|
precipitation, etc.) has configurable thresholds:
|
||||||
|
|
||||||
- `good` below/above this (depending on sign) the condition is good.
|
- `good` — below/above this (depending on sign) the condition is good.
|
||||||
- `bad` above this the condition is bad.
|
- `bad` — above this the condition is bad.
|
||||||
- `terrible` above this the condition is terrible.
|
- `terrible` — above this the condition is terrible.
|
||||||
- `prohibited` (if defined) above this the condition goes directly to PROHIBITED.
|
- `prohibited` — (if defined) above this the condition goes directly to PROHIBITED.
|
||||||
- `negflag` if `1`, a smaller value is worse (e.g., clouds).
|
- `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.
|
- `shtdnflag` — if `1`, entering the terrible/prohibited range also sets the **FORCE SHUTDOWN** flag.
|
||||||
|
|
||||||
### Special Flags
|
### Special Flags
|
||||||
|
|
||||||
@@ -251,9 +251,9 @@ passed since the last serious event. This prevents rapid toggling.
|
|||||||
|
|
||||||
The daemon listens on two interfaces:
|
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.
|
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.
|
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
|
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=<N>` each `KEY` have a suffix in square
|
usually echo back the variable and its new value. For `get=<N>` 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
|
## Signals
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,9 @@
|
|||||||
# small_tel
|
# small_tel
|
||||||
|
|
||||||
Different utilities for small telescopes
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user