feat: v0.3.9 - /me command, weather with pressure and dewpoint
Add /me command showing requesting node's info. Add sea-level pressure and dewpoint to weather response. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d9889787a0
commit
50e12fbe02
|
|
@ -1,5 +1,10 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.3.9] - 2026-02-16
|
||||||
|
### Added
|
||||||
|
- Neuer Befehl `/me` zeigt eigene Node-Infos (Name, HW, Hops, SNR, RSSI, Batterie, Position)
|
||||||
|
- Wetter zeigt Luftdruck NN (hPa) und Taupunkt (°C)
|
||||||
|
|
||||||
## [0.3.8] - 2026-02-16
|
## [0.3.8] - 2026-02-16
|
||||||
### Changed
|
### Changed
|
||||||
- Ping-Antwort zeigt Hop-Anzahl des anfragenden Nodes (z.B. "Pong ueber 2 Hops!")
|
- Ping-Antwort zeigt Hop-Anzahl des anfragenden Nodes (z.B. "Pong ueber 2 Hops!")
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
version: "0.3.8"
|
version: "0.3.9"
|
||||||
|
|
||||||
bot:
|
bot:
|
||||||
name: "MeshDD-Bot"
|
name: "MeshDD-Bot"
|
||||||
|
|
|
||||||
|
|
@ -286,10 +286,14 @@ class MeshBot:
|
||||||
f"{prefix}stats - Statistiken\n"
|
f"{prefix}stats - Statistiken\n"
|
||||||
f"{prefix}uptime - Laufzeit\n"
|
f"{prefix}uptime - Laufzeit\n"
|
||||||
f"{prefix}weather [plz:XXXXX] - Wetter\n"
|
f"{prefix}weather [plz:XXXXX] - Wetter\n"
|
||||||
|
f"{prefix}me - Meine Node-Infos\n"
|
||||||
f"{prefix}mesh - Mesh-Netzwerk\n"
|
f"{prefix}mesh - Mesh-Netzwerk\n"
|
||||||
f"{prefix}help - Diese Hilfe"
|
f"{prefix}help - Diese Hilfe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
elif cmd == f"{prefix}me":
|
||||||
|
response = await self._get_my_info(from_id)
|
||||||
|
|
||||||
elif cmd == f"{prefix}weather":
|
elif cmd == f"{prefix}weather":
|
||||||
args = text.split()[1:]
|
args = text.split()[1:]
|
||||||
plz = None
|
plz = None
|
||||||
|
|
@ -385,6 +389,51 @@ class MeshBot:
|
||||||
parts.append(f"{seconds}s")
|
parts.append(f"{seconds}s")
|
||||||
return " ".join(parts)
|
return " ".join(parts)
|
||||||
|
|
||||||
|
async def _get_my_info(self, from_id: str) -> str:
|
||||||
|
if not from_id:
|
||||||
|
return "❌ Node-ID unbekannt."
|
||||||
|
node = await self.db.get_node(from_id)
|
||||||
|
if not node:
|
||||||
|
return f"❌ Keine Daten fuer {from_id}."
|
||||||
|
|
||||||
|
name = node.get("long_name") or node.get("short_name") or from_id
|
||||||
|
hw = node.get("hw_model") or "-"
|
||||||
|
hops = node.get("hop_count") if node.get("hop_count") is not None else "-"
|
||||||
|
snr = f"{node['snr']:.1f} dB" if node.get("snr") is not None else "-"
|
||||||
|
rssi = f"{node['rssi']} dBm" if node.get("rssi") is not None else "-"
|
||||||
|
bat = f"{node['battery']}%" if node.get("battery") is not None else "-"
|
||||||
|
voltage = f"{node['voltage']:.2f}V" if node.get("voltage") is not None else "-"
|
||||||
|
alt = f"{int(node['alt'])} m" if node.get("alt") is not None else "-"
|
||||||
|
pos = ""
|
||||||
|
if node.get("lat") and node.get("lon"):
|
||||||
|
pos = f"{node['lat']:.4f}, {node['lon']:.4f}"
|
||||||
|
last_seen = ""
|
||||||
|
if node.get("last_seen"):
|
||||||
|
elapsed = int(time.time() - node["last_seen"])
|
||||||
|
if elapsed < 60:
|
||||||
|
last_seen = f"{elapsed}s"
|
||||||
|
elif elapsed < 3600:
|
||||||
|
last_seen = f"{elapsed // 60}m"
|
||||||
|
elif elapsed < 86400:
|
||||||
|
last_seen = f"{elapsed // 3600}h"
|
||||||
|
else:
|
||||||
|
last_seen = f"{elapsed // 86400}d"
|
||||||
|
|
||||||
|
lines = [
|
||||||
|
f"📋 {name}",
|
||||||
|
f"ID: {from_id}",
|
||||||
|
f"HW: {hw}",
|
||||||
|
f"Hops: {hops}",
|
||||||
|
f"SNR: {snr} | RSSI: {rssi}",
|
||||||
|
f"Bat: {bat} ({voltage})",
|
||||||
|
]
|
||||||
|
if pos:
|
||||||
|
lines.append(f"Pos: {pos} | {alt}")
|
||||||
|
if last_seen:
|
||||||
|
lines.append(f"Zuletzt: vor {last_seen}")
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
async def _get_mesh_info(self) -> str:
|
async def _get_mesh_info(self) -> str:
|
||||||
nodes = await self.db.get_all_nodes()
|
nodes = await self.db.get_all_nodes()
|
||||||
total = len(nodes)
|
total = len(nodes)
|
||||||
|
|
@ -446,7 +495,7 @@ class MeshBot:
|
||||||
url = (
|
url = (
|
||||||
f"https://api.open-meteo.com/v1/forecast?"
|
f"https://api.open-meteo.com/v1/forecast?"
|
||||||
f"latitude={lat}&longitude={lon}"
|
f"latitude={lat}&longitude={lon}"
|
||||||
f"¤t=temperature_2m,relative_humidity_2m,wind_speed_10m,weather_code"
|
f"¤t=temperature_2m,relative_humidity_2m,wind_speed_10m,weather_code,pressure_msl,dew_point_2m"
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -457,6 +506,8 @@ class MeshBot:
|
||||||
humidity = current.get("relative_humidity_2m", "?")
|
humidity = current.get("relative_humidity_2m", "?")
|
||||||
wind = current.get("wind_speed_10m", "?")
|
wind = current.get("wind_speed_10m", "?")
|
||||||
code = current.get("weather_code", 0)
|
code = current.get("weather_code", 0)
|
||||||
|
pressure = current.get("pressure_msl", "?")
|
||||||
|
dewpoint = current.get("dew_point_2m", "?")
|
||||||
weather_icon = self._weather_code_to_icon(code)
|
weather_icon = self._weather_code_to_icon(code)
|
||||||
|
|
||||||
location = await self._reverse_geocode(lat, lon)
|
location = await self._reverse_geocode(lat, lon)
|
||||||
|
|
@ -465,6 +516,8 @@ class MeshBot:
|
||||||
f"{weather_icon} Wetter{loc_str}:\n"
|
f"{weather_icon} Wetter{loc_str}:\n"
|
||||||
f"Temp: {temp}°C\n"
|
f"Temp: {temp}°C\n"
|
||||||
f"Feuchte: {humidity}%\n"
|
f"Feuchte: {humidity}%\n"
|
||||||
|
f"Taupunkt: {dewpoint}°C\n"
|
||||||
|
f"Luftdruck: {pressure} hPa\n"
|
||||||
f"Wind: {wind} km/h"
|
f"Wind: {wind} km/h"
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue