Rebrand CommGate to gsmnode and adopt new design system
Rename the whole project from CommGate to gsmnode and re-skin every surface onto the new signal-green + ink design system (Space Grotesk / IBM Plex Sans / JetBrains Mono, flat surfaces, two-arrow routing mark, lowercase gsm+node wordmark). - Web App + API panel: rewrite token layer, gn-* utilities, data-gsm-theme, new logo/favicon assets; both builds verified. - Phone App (Flutter): green theme, new mark/wordmark widgets, adaptive launcher icons; rename Android applicationId/package to app.gsmnode.phone; bump AGP to 8.6.0 and google_fonts to 8.1.0; debug APK build verified. - API Server (Go): panel routes, User-Agent, health service id, branding. - Home Assistant Plugin: rename integration domain sms_gateway to gsmnode (folder, DOMAIN, services, entity ids, classes); py_compile verified. - Update all READMEs; add .gitignore (excludes Design/, build artifacts). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
"""The gsmnode integration.
|
||||
|
||||
Sends SMS and places phone calls through the gsmnode API Server. Configured
|
||||
from the UI (Settings → Devices & Services → Add Integration → gsmnode).
|
||||
|
||||
Exposes two services — `gsmnode.send_sms` and `gsmnode.call` — and an
|
||||
"API Server" connectivity binary sensor. A legacy `notify.gsmnode` platform
|
||||
(YAML) is also available for backward compatibility (see notify.py / README).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from .client import GsmNodeClient, GsmNodeConnectionError
|
||||
from .const import (
|
||||
CONF_API_BASE,
|
||||
CONF_DEVICE_ID,
|
||||
DOMAIN,
|
||||
SERVICE_CALL,
|
||||
SERVICE_SEND_SMS,
|
||||
)
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR]
|
||||
|
||||
SEND_SMS_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("phone_numbers"): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Required("message"): cv.string,
|
||||
vol.Optional("device_id"): cv.string,
|
||||
vol.Optional("sim_number"): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
|
||||
CALL_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("phone_number"): cv.string,
|
||||
vol.Optional("device_id"): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up gsmnode from a config entry."""
|
||||
client = GsmNodeClient(
|
||||
hass,
|
||||
entry.data[CONF_API_BASE],
|
||||
entry.data[CONF_EMAIL],
|
||||
entry.data[CONF_PASSWORD],
|
||||
entry.data.get(CONF_DEVICE_ID),
|
||||
)
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = client
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
_async_register_services(hass)
|
||||
return True
|
||||
|
||||
|
||||
def _async_register_services(hass: HomeAssistant) -> None:
|
||||
"""Register the send_sms / call services (once)."""
|
||||
if hass.services.has_service(DOMAIN, SERVICE_SEND_SMS):
|
||||
return
|
||||
|
||||
def _first_client() -> GsmNodeClient | None:
|
||||
for value in hass.data.get(DOMAIN, {}).values():
|
||||
if isinstance(value, GsmNodeClient):
|
||||
return value
|
||||
return None
|
||||
|
||||
async def handle_send_sms(call: ServiceCall) -> None:
|
||||
client = _first_client()
|
||||
if client is None:
|
||||
raise GsmNodeConnectionError("no gsmnode configured")
|
||||
await client.send_sms(
|
||||
call.data["phone_numbers"],
|
||||
call.data["message"],
|
||||
call.data.get("device_id"),
|
||||
call.data.get("sim_number"),
|
||||
)
|
||||
|
||||
async def handle_call(call: ServiceCall) -> None:
|
||||
client = _first_client()
|
||||
if client is None:
|
||||
raise GsmNodeConnectionError("no gsmnode configured")
|
||||
await client.place_call(call.data["phone_number"], call.data.get("device_id"))
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SEND_SMS, handle_send_sms, schema=SEND_SMS_SCHEMA
|
||||
)
|
||||
hass.services.async_register(DOMAIN, SERVICE_CALL, handle_call, schema=CALL_SCHEMA)
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].pop(entry.entry_id, None)
|
||||
if not hass.data[DOMAIN]:
|
||||
hass.services.async_remove(DOMAIN, SERVICE_SEND_SMS)
|
||||
hass.services.async_remove(DOMAIN, SERVICE_CALL)
|
||||
return unload_ok
|
||||
Reference in New Issue
Block a user