# Plano de integração — CELESC (energia) + SolarMan (usina solar)

**Data:** 2026-07-11 · **Base:** engenharia reversa dos HARs que você enviou (2 rodadas
de captura) + planilha de geração. **Status: engenharia reversa COMPLETA** — auth,
endpoints E formatos de resposta dos dois sistemas estão confirmados (2ª captura trouxe
os headers de autenticação e os corpos de resposta que faltavam). Não há mais incógnitas
técnicas; dá para implementar direto.

**Resumo em uma linha:** os dois são **viáveis e comprovados**. A CELESC expõe uma API
GraphQL completa (contas, situação paga/em aberto, consumo, 2ª via) e o SolarMan expõe uma
API REST (usina online/offline, geração agora/dia/mês/total, alertas dos inversores).
Ambos usam `Authorization: Bearer` e encaixam no MESMO padrão que o Nexus já usa para o
**Omada** (cliente App self-contained + `.env` + módulo com kill-switch + worker + KV
cache + painel).

---

## 0. ⚠️ Segurança — leia primeiro

Os arquivos `.har` que você enviou **contêm credenciais reais em texto** (confirmado):

- **SolarMan:** o corpo do login (`/oauth2-s/oauth/token`) traz a sua **senha em texto
  puro** no campo `clear_text_pwd` + o e-mail. Qualquer pessoa com o HAR entra na sua
  conta. **Já apareceu em DUAS capturas suas** — trate como comprometida.
- **CELESC:** traz o e-mail e o **token Bearer** de sessão (opaco, 88 chars). O token
  expira, mas o login está no arquivo.

**Ações recomendadas ANTES de qualquer coisa:**
1. **Troque a senha do SolarMan** — ela está exposta no arquivo.
2. Não versione esses `.har` no Git nem os deixe em pasta pública. Guarde as
   credenciais só no `.env` (fora do `public/`), como já é o padrão do projeto.
3. Na integração, as senhas ficam **apenas** no `.env` do servidor
   (`CELESC_*`, `SOLARMAN_*`), nunca no banco nem no front.

---

## 1. CELESC — o que dá para fazer

**Portal:** `conecte.celesc.com.br` ("Minha Celesc / Agência Virtual"). **Não há
API oficial pública** — é a API interna do próprio portal (GraphQL). A integração é
**engenharia reversa**, no mesmo espírito do que já fazemos com o InControl e a
Defesa Civil SC: é a **sua própria conta**, lendo os **seus** dados.

### 1.1 Autenticação (provado no HAR)
```
POST https://conecte.celesc.com.br/auth/login
Content-Type: application/json
{ "username": "<email>", "password": "<senha>", "channel": "ZAW",
  "socialCode": "", "socialRedirectUri": "", "accessIp": "",
  "deviceId": "server", "firebaseToken": "" }
→ data.authenticate.login.accessToken   (token OPACO, 88 chars, tokenType "opaque")
   data.authenticate.sapAccess.{ partner, accessId, userId, ... }
```
**Autenticação confirmada (2ª captura):** as chamadas seguintes levam
`Authorization: Bearer <accessToken>`. Sem mais incógnitas — o cliente faz login,
guarda o token e o manda no header (re-loga sozinho ao levar 401, como o
`InControlService`). Obs.: o `accessId` muda a cada sessão (é do login), o `partner`/
`installation`/`contractAccount` são fixos.

### 1.2 Identificadores da sua conta (extraídos do HAR)
- `partner` (titular): `0063743402`
- `installation` (unidade consumidora): `194939501101`
- `contractAccount` (conta contrato): `29810303`
- `accessId`: `00000000000097301035`

### 1.3 Consultas úteis (todas GraphQL em `/graphql`, provadas no HAR)

| Objetivo | Operação | Retorna |
|---|---|---|
| **Unidades consumidoras** | `allContracts(partner, profileType)` | lista de UCs: instalação, endereço, tarifa, status |
| **Contas / faturas** | `getAllBills(partner, installation, contractAccount)` | **29 faturas** com `dueDate`, `totalAmount`, `consumption`, `previousUsage`, `flag` (bandeira), `billingPeriod`, **`compensation`** ("Paga"/em aberto), `compensationDate`, `codigoDeBarras`, `qrCode` (pix) |
| **Parcelamentos** | `getInstallmentBills(...)` | parcelas em aberto |
| **Vencimentos alternativos** | `allAvailableDueDates(...)` | opções de data de vencimento |
| **Datas de leitura** | `getReadingDates(...)` | período faturado, dias, data de leitura |
| **Comparativo de contas** | `getBillsAnalysis(...)` | variação entre 2 faturas |
| **2ª via (PDF)** | `duplicateBill(...)` (mutation) | PDF em base64 |

### 1.4 O que você pediu → como fica
- **"contas estão pagas?"** → `getAllBills` traz `compensation` + `compensationDate`
  por fatura. Dá para mostrar um selo **Paga / Em aberto / Vencida** e alertar quando
  houver conta vencendo/vencida.
- **"consumo do último mês"** → `getAllBills[0]` = período mais recente (ex.: **2026/06,
  704 kWh, R$ 186,67, bandeira Amarela, paga em 08/07**). Dá para gráfico de 12 meses.
- **Bônus fácil:** bandeira tarifária do mês, comparação com o mês anterior, botão de
  2ª via (PDF), e — porque você tem usina — os campos de **energia compensada** (a conta
  já traz `generatedConsumption`, útil para casar com a geração do SolarMan).

**Amostra real dos seus dados (últimas contas):**
```
2026/06  venc 07/07  R$ 186,67   704 kWh  Amarela   → Paga (08/07)
2026/05  venc 08/06  R$ 210,96  1076 kWh  Verde     → Paga
2026/04  venc 07/05  R$ 279,64  1999 kWh  Verde     → Paga
2026/01  venc 09/02  R$ 297,68  2107 kWh  Amarela   → Paga
```

---

## 2. SolarMan — o que dá para fazer

**App:** `SOLARMAN Smart` (`globalhome.solarmanpv.com`). Sua usina é a estação
**`1613115` — "GL Consultoria"**. Aqui há **dois caminhos**, e a decisão é sua (§7):

**Sua usina (dados reais extraídos):** "GL Consultoria", estação `1613115`, telhado,
**75 kW instalados**, em Balneário Piçarras/SC (-26.766, -48.670), operando desde
fev/2022, fuso America/Sao_Paulo. Geração acumulada **380.165 kWh** (R$ 281.322);
mês atual **1.842 kWh** (R$ 1.363). 2 inversores + 1 datalogger (SN 4054018027).

### 2.1 Caminho A — API interna do app (100% provado, funciona já)
Mesma lógica da CELESC: login com usuário/senha → token JWT (Bearer) → chamadas REST.
```
POST /oauth2-s/oauth/token   (application/x-www-form-urlencoded)
  grant_type=mdc_password & username=<email> & clear_text_pwd=<senha> & password=<sha> & area=BR & client_id=test
→ access_token (JWT RS256 → Authorization: Bearer nas chamadas seguintes)
```
Endpoints REST provados **com os campos de resposta confirmados** (ID `1613115`):

| Objetivo | Endpoint | Campos que usamos |
|---|---|---|
| **Usina online? saúde** | `GET /maintain-s/operating/system/1613115` | `networkStatus` (NORMAL/…), `warningStatus`, `businessWarningStatus`, `generationPower` (W agora), `generationTotal` (kWh) |
| **Potência/geração agora** | `GET /maintain-s/fast/system/1613115` | `generationValue` (kWh **hoje**), `generationPower` (W), `fullPowerHoursDay` |
| **Dados estáticos** | `GET /maintain-s/station/1613115/detail` | `installedCapacity` (75 kW), `location`, `startOperatingTime` |
| **Geração mês/ano/total** | `GET /maintain-s/history/power/1613115/stats/{month\|year\|total}` | `generationValue` (kWh), `incomeValue` (R$) |
| **Curva do dia** | `GET /maintain-s/history/power/analysis/1613115/day` | série intradiária |
| **Alertas / falhas** | `POST /maintain-s/operating/alert/search` `{plantId,language:"pt"}` | `showName` (ex.: "PV Isolation Protection"), `level`, `deviceSn`, `alertTime` |
| **Inversores + status** | `GET /maintain-s/fast/device/1613115/device-list` | `deviceSn`, `deviceStatus`, `generationPower`, `generation` |

> **Achado relevante:** no momento da captura a usina tinha **8 alertas ativos** (ex.:
> "PV Isolation Protection" nível 2 e "Leakage Current Protection" no inversor
> 1143D2223140070). É exatamente o tipo de coisa que você quer que o painel avise.

### 2.2 Caminho B — SolarMan Open API oficial (recomendado, mais estável)
O SolarMan (IGEN Tech) oferece uma **API de negócio oficial** com `appId`/`appSecret`
que você solicita ao **seu integrador/distribuidor**. É a via sancionada: contrato
estável, não quebra quando eles mudam o app. Endpoints equivalentes (lista de usinas,
tempo real, histórico, dados do inversor). **Desvantagem:** depende de pedir a chave ao
instalador (pode levar alguns dias).

### 2.3 O que você pediu → como fica
- **"fazenda está online?"** → status do sistema + do datalogger; se cair, dispara
  alerta ("usina offline há X min") pelos canais que você já usa (Pushover/WhatsApp/push).
- **"como está a geração"** → potência **agora** (`generationPower`), **hoje**
  (`fast/system.generationValue`), **mês** e **total** com R$ (`stats/*.incomeValue`),
  com gráfico. Confirmado nos dados: mês atual 1.842 kWh / R$ 1.363; total 380 MWh.
- **Bônus:** os 8 alertas ativos já saem prontos do `alert/search`; dá para alerta de
  **geração zero em horário de sol** (inversor travado), saúde de cada inversor, e
  cruzar geração (SolarMan) × energia compensada (CELESC).

---

## 3. Arquitetura proposta (espelha o módulo Omada — §5.24 do CLAUDE.md)

Nada de padrão novo: reaproveitamos o que já existe e funciona.

```
api/app/Energy/CelescClient.php     # cliente self-contained (cURL puro, token em cache) — como OmadaClient
api/app/Energy/SolarmanClient.php   # idem (OAuth2)
api/config/celesc.php  + .env       # CELESC_ENABLED, CELESC_USER, CELESC_PASS, CELESC_* ids
api/config/solarman.php + .env      # SOLARMAN_ENABLED, SOLARMAN_* (ou appId/appSecret no caminho B)
App\Support\Modules                 # 2 módulos novos no kill-switch: 'celesc', 'solarman' (grupo Integrações)
api/scripts/celesc_sync.php + .bat  # worker ~6h: puxa faturas/consumo → KV + alertas de conta vencendo
api/scripts/solarman_sync.php + .bat# worker ~15min: status/geração → KV + alerta offline/geração-zero
api/scripts/celesc_test.php         # CLI de validação (roda com _ENABLED=false), como omada_test.php
api/scripts/solarman_test.php       # idem
app/Controllers/EnergyController.php # painel /energia (leitura da KV, sem chamada externa no request)
app/Views/energia/panel.php         # cards: contas (paga/aberta), consumo 12m, usina online, geração
deploy/INTEGRACAO-CELESC.md         # guia leigo (padrão INTEGRACAO-MQTT.md)
deploy/INTEGRACAO-SOLARMAN.md       # idem
```

Princípios que já são lei no projeto e se aplicam aqui:
- **Best-effort + degradação graciosa:** nuvem fora do ar → o painel mostra o último
  dado do cache com "atualizado há X" (padrão do `/clima` e do Mural). Nada trava.
- **KV cache** (`configuracao`): o worker persiste o snapshot; a tela só lê (rápido,
  sem depender do portal no momento do acesso).
- **Kill-switch por módulo** (`/modulos`): liga/desliga cada integração sem mexer em código.
- **Credenciais só no `.env`**, nunca no banco/front.
- **Alertas pelos canais existentes** (`AlertService`): Pushover/Resend/WhatsApp/Web Push
  já prontos — só criamos os gatilhos (conta vencendo, usina offline, geração zero).

### 3.1 Onde aparece para o usuário
- **Nova tela `/energia`** (ability `energy.view`, menu em Início) com 4 blocos:
  contas CELESC (situação + próximo vencimento + botão 2ª via), consumo 12 meses,
  usina SolarMan (online + potência agora + geração hoje/mês), e geração × consumo.
- **Central de operação** ganha 2 linhas: "usina offline" e "conta vencendo" entram
  nos "problemas" (reusa o padrão que já existe).
- **Opcional — Sub-medição (§5.7):** a geração do SolarMan e o consumo da CELESC podem
  virar **medidores** (`medidor` tipo `energia`), aproveitando os gráficos e a IA de
  anomalia que já temos, sem tela nova.

---

## 4. Modelo de dados

Duas tabelas de cache/histórico (schema + migração, padrão do projeto):

- **`energia_conta`** (CELESC): `installation`, `contract_account`, `periodo` (AAAA/MM),
  `vencimento`, `valor`, `consumo_kwh`, `bandeira`, `situacao` (paga/aberta/vencida),
  `pago_em`, `codigo_barras`, `pix`, `atualizado_em`. UNIQUE (installation, periodo).
- **`energia_geracao`** (SolarMan): `station_id`, `data`, `producao_kwh`, `rendimento`,
  `pico_kw`, `online`, `atualizado_em`. UNIQUE (station_id, data).

Snapshots "ao vivo" (usina online, potência agora, próxima conta) ficam na KV
`configuracao` (`celesc_panel`, `solarman_panel`) — igual ao `weather_panel`.

---

## 5. Plano em fases

**Fase 0 — Segurança (você, agora):** trocar a senha do SolarMan; decidir os 2 pontos
do §7.

**Fase 1 — CELESC (base):** `CelescClient` + `celesc_test.php` (confirma o header de
auth ao vivo) + `.env`. Entrega: no terminal, listar contas e situação. ~0,5–1 dia.

**Fase 2 — CELESC (produto):** worker `celesc_sync` (KV + tabela + alerta de conta
vencendo) + painel `/energia` (bloco contas + consumo). ~1 dia.

**Fase 3 — SolarMan (base):** `SolarmanClient` + `solarman_test.php` (confirma os
campos de resposta ao vivo) + `.env`. Entrega: no terminal, status online + geração do
dia. ~0,5–1 dia (caminho A) / +espera da chave (caminho B).

**Fase 4 — SolarMan (produto):** worker `solarman_sync` (KV + tabela + alerta offline /
geração-zero) + bloco usina no `/energia` + entrada na Central. ~1 dia.

**Fase 5 — Extras (opcional):** medidores `energia` (§5.7), gráfico geração × consumo,
guias `deploy/INTEGRACAO-*.md` no formato para leigos. ~0,5–1 dia.

**Total estimado:** ~3,5–5 dias de desenvolvimento, entregável fase a fase (cada fase
já roda sozinha).

---

## 6. Riscos e mitigações

- **É engenharia reversa (CELESC sempre; SolarMan no caminho A).** Se o portal mudar,
  a integração pode quebrar. Mitigação: cliente isolado com **paths centralizados** (um
  lugar só para ajustar), CLI de teste para revalidar rápido, e kill-switch para desligar
  sem afetar o resto. É exatamente como convivemos com InControl/Defesa Civil/Omada.
- **Rate limit / bloqueio:** os workers rodam em intervalos folgados (CELESC ~6h,
  SolarMan ~15min) e cacheiam — sem marteladas no portal.
- **Termos de uso:** é a sua conta e os seus dados, para uso próprio. Ainda assim,
  a via oficial (SolarMan caminho B) elimina esse risco do lado da usina.
- **Token opaco da CELESC:** expira; o cliente re-loga sozinho quando levar 401 (padrão
  do `InControlService`).

---

## 7. Decisões que preciso de você (antes de implementar)

1. **CELESC — seguimos por engenharia reversa?** Não existe API oficial; é a única via.
   É a sua conta lendo os seus dados (como já fazemos com o InControl). Auth já provada
   (Bearer). OK?
2. **SolarMan — caminho A (reverso, **agora 100% provado ponta a ponta**) ou B (Open API
   oficial, pede `appId/appSecret` ao seu instalador, mais estável)?** O A funciona já;
   posso começar por ele e migrar para o B quando a chave chegar — as duas falam com o
   mesmo painel.
3. **Escopo da 1ª entrega:** começo pela **CELESC** (contas/consumo) ou pela **usina**
   (online/geração)? Ou as duas em paralelo?

Me diga esses 3 pontos e eu já começo pela Fase 1. Com a 2ª captura, a engenharia
reversa está fechada — a implementação é direta.
