Mapa da aula
Aula 09 publicada. Mapa, exemplo, EX025.
flowchart TD
N0["9.1 O papel do historiador"]
N1["9.2 Um esquema mínimo"]
N2["9.3 Agregados escondem eventos"]
N3["Síntese"]
N0 --> N1 --> N2 --> N3
N3 --> EX["Exemplo resolvido"]
EX --> Q["Exercício EX025"]
Desenho lógico
flowchart LR
N0["9.1 O papel do historiador"]
N1["9.2 Um esquema mínimo"]
N2["9.3 Agregados escondem eventos"]
N3["Síntese"]
N0 --> N1 --> N2 --> N3 --> Q["EX025"]
[9.1 O papel do historiador]
|
v
[9.2 Um esquema mínimo]
|
v
[9.3 Agregados escondem eventos]
|
v
[Síntese]
|
v
[Exemplo resolvido] --> [Exercício EX025]
Objetivos de aprendizagem
Você vai (1) modelar os dados do historiador como tempo, tag e valor; (2) agregar e filtrar com SQL no SQLite; (3) detectar lacunas de amostragem; e (4) explicar por que o historiador é ao mesmo tempo um ativo e um risco de segurança.
9.1 O papel do historiador
Um historiador de processo armazena séries temporais vindas dos controladores para tendências, relatórios e investigações. Como fica entre as redes de controle e de negócio, ele é muitas vezes a ponte que um intruso usa — e também o melhor registro de que um investigador dispõe. O NIST SP 800-82r3 recomenda colocar numa cópia na DMZ os dados de que os usuários de negócio precisam, para que os usuários corporativos nunca consultem diretamente o historiador da zona de controle. Na LDHP, o HIST-1 fica no nível 3 de Purdue. Os usuários de faturamento e de análise devem ler uma réplica na DMZ, para que uma conta de escritório comprometida nunca abra uma sessão com o historiador que também coleta do PLC-H.
9.2 Um esquema mínimo
Três colunas — carimbo de tempo, tag e valor — carregam a maior parte do conteúdo de um historiador; os sistemas de produção acrescentam códigos de qualidade e compressão. O SQLite, embutido no Python, é suficiente para aprender as consultas.
"""Lab 09: query a synthetic historian in an in-memory SQLite database."""
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("create table h(ts integer, tag text, v real)")
rows = [(t, "TT-101", 90 + (t % 5)) for t in range(0, 60, 5)] + [(t, "PT-201", 9.5) for t in range(0, 60, 10)]
rows.append((35, "TT-101", 128.0))
db.executemany("insert into h values(?,?,?)", rows)
for tag, n, mx, mean in db.execute("select tag,count(*),max(v),round(avg(v),2) from h group by tag order by tag"):
print(f"{tag}: n={n} max={mx} mean={mean}")
print("excursions >120:", db.execute("select ts,v from h where tag='TT-101' and v>120").fetchall())
print("gap check PT-201 samples:", [r[0] for r in db.execute("select ts from h where tag='PT-201' order by ts")])
Execute com python3 lab_hist.py. Saída verificada:
PT-201: n=6 max=9.5 mean=9.5
TT-101: n=13 max=128.0 mean=92.92
excursions >120: [(35, 128.0)]
gap check PT-201 samples: [0, 10, 20, 30, 40, 50]
A tabela do laboratório guarda amostras de TT-101 e PT-201 com carimbos de tempo inteiros, o suficiente para executar as duas perguntas que um operador mais faz: qual foi o extremo, e está faltando alguma coisa. A resposta de Maya sobre a sobretemperatura veio de uma consulta sobre essa tabela: select ts, v from h where tag='TT-101' and v > 120, que devolveu uma linha em t = 35, 128 °C, de 13 amostras examinadas. O painel de médias horárias não tinha mostrado nada de incomum no mesmo turno.
9.3 Agregados escondem eventos
A média de 92,92 °C de TT-101 parece normal; o máximo de 128,0 °C em t = 35, não. Sempre junte uma média a um extremo e a uma contagem. A verificação de lacunas confirma que PT-201 foi amostrado a cada 10 unidades de tempo, sem perdas; um carimbo de tempo ausente nessa lista seria o primeiro sinal de uma falha de coleta ou de supressão deliberada. O relatório de Maya declara os três: uma excursão a 128,0 °C em t = 35, 13 amostras examinadas e o ponto de trip suposto de 135 °C do SIS-H não alcançado. O painel de médias horárias tinha respondido "nenhuma sobretemperatura" à mesma pergunta.
Exemplo resolvido (LDHP sintética)
Perguntam a Maya: "Houve alguma sobretemperatura no último turno?" Um painel de médias horárias diz que não. A consulta dela, select ts, v from h where tag='TT-101' and v > 120, devolve uma excursão em t = 35, 128 °C. Ela a relata com a contagem de amostras examinadas (13) e observa que o ponto de trip do SIS-H (suposto em 135 °C nesta planta sintética) não foi alcançado.
Caso sintético — Lakeside District Heating Plant. Os valores, as tags e o ponto de trip de 135 °C foram inventados para o ensino.
Erros e limites
A compressão do historiador (banda morta ou swinging door) pode descartar pontos que não mudaram "o suficiente", de modo que picos curtos podem estar ausentes. Os carimbos de tempo podem vir do historiador, e não do controlador. Nunca conceda acesso de escrita às tabelas do historiador para trabalho de análise.
Exercícios
- EX025 — Contando as amostras examinadas. Por que o laboratório relata n = 13 para TT-101, e não 12?
Mostrar critérios de avaliação
Rubrica: 3 = 12 amostras regulares (0–55, passo 5) mais a excursão inserida; 2 = nota a linha extra; 1 = chuta; 0 = nada. - EX026 — Consulta para uma lacuna de amostragem. Escreva um SQL que devolva os carimbos de tempo de PT-201 em que a amostra seguinte chega mais de 10 unidades depois.
Mostrar critérios de avaliação
Rubrica: 3 = função de janela LEAD (ou auto-junção) com diferença de ts > 10; 2 = ideia correta, deslize de sintaxe; 1 = só conta linhas; 0 = nada. - EX027 — Compressão por banda morta e picos. Explique como a compressão por banda morta poderia esconder uma excursão breve.
Mostrar critérios de avaliação
Rubrica: 3 = ponto armazenado apenas quando muda além da banda morta ou por exceção/heartbeat, então um pico curto entre pontos armazenados pode sumir; 2 = parcial; 1 = só "a compressão perde dados"; 0 = nada.
Síntese
Peça ao historiador extremos, contagens e lacunas, e não só médias — e trate a sua localização e as suas permissões como projeto de segurança.