Projeto para Linux com foco em operacao industrial:
- relay UDP de 1 a 4 scanners
- fan-out para um ou mais destinos por scanner
- interpretacao dos telegramas UDP do SICK nanoScan3
- servidor web leve para visualizar os dados interpretados
- parser UDP do nanoScan3 em
src/nanoscan_parser.py - store thread-safe de telemetria em
src/telemetry_store.py - servidor web HTTP (API + pagina) em
src/web_server.py - integracao no loop do relay para interpretar sem parar o encaminhamento UDP
Implementacao baseada na estrutura de parsing dos repositorios oficiais da SICK:
.
├── README.md
├── requirements.txt
├── config
│ └── relay_config.example.json
├── scripts
│ └── udp_scanner_simulator.py
├── src
│ ├── config_loader.py
│ ├── logger_setup.py
│ ├── main.py
│ ├── models.py
│ ├── nanoscan_parser.py
│ ├── stats.py
│ ├── telemetry_store.py
│ ├── udp_relay.py
│ ├── utils.py
│ └── web_server.py
└── systemd
└── udp-relay.service
- Python 3.10+
- NumPy (para parse vetorizado com menor CPU)
Instalacao:
python3 -m pip install -r requirements.txtlog_leveldebugstats_interval_secrecv_socket_buffer_bytessend_socket_buffer_bytesmax_expected_packet_sizesource_ip_filter_enabledcpu_affinitynicescanner_timeout_secmax_packets_per_socket_event
enabled: habilita API/webhost: ex.0.0.0.0port: ex.8080max_sample_points: limita pontos enviados na API (reduz CPU/rede)parse_every_n_packets: interpreta 1 a cada N pacotes (reduz CPU)parse_mode:full(mais detalhado) ouminimal(menos CPU)
Cada scanner:
nameenabledsource_ip(opcional)invert_scan_direction(opcional, defaultfalse; usetruepara instalacao de ponta-cabeca)local_portdestinations: lista de{ "ip", "port" }
{
"general": {
"log_level": "INFO",
"debug": false,
"stats_interval_sec": 5.0,
"recv_socket_buffer_bytes": 1048576,
"send_socket_buffer_bytes": 262144,
"max_expected_packet_size": 4096,
"source_ip_filter_enabled": true,
"cpu_affinity": [2],
"nice": 5,
"scanner_timeout_sec": 2.0,
"max_packets_per_socket_event": 128
},
"web": {
"enabled": true,
"host": "0.0.0.0",
"port": 8080,
"max_sample_points": 360,
"parse_every_n_packets": 1,
"parse_mode": "full"
},
"scanners": [
{
"name": "scanner_frontal",
"enabled": true,
"source_ip": "192.168.10.101",
"invert_scan_direction": false,
"local_port": 21110,
"destinations": [
{ "ip": "192.168.10.10", "port": 21100 },
{ "ip": "192.168.20.50", "port": 25000 }
]
}
]
}Validar config:
python3 src/main.py --config config/relay_config.example.json --validate-configRodar:
python3 src/main.py --config config/relay_config.example.jsonCom web.enabled=true, o processo sobe HTTP com:
GET /-> pagina HTML de monitoramentoGET /health-> health checkGET /api/scanners-> estado de todos scannersGET /api/scanners/<nome>-> estado de um scanner
Visualizacao:
- desenho polar dos raios no canvas
- faixa angular fixa de fundo:
-47.5°a222.5°(270°) - respeita
invert_scan_directionpor scanner para inverter o sentido dos raios - zoom por scanner com scroll do mouse
- zoom maximo de
200x - arraste com mouse para mover o centro do scanner (pan)
- duplo clique no canvas para resetar zoom
Exemplo:
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/api/scannersPor scanner (quando telegrama completo do nanoScan3 e parse valido):
sequence_number,scan_number,channel_numbernumber_of_beamsstart_angle_deg,angular_beam_resolution_degscan_time_ms,interbeam_period_us- contadores de status (
valid,infinite,glare,reflector,contamination) min_range_m,max_range_m- amostragem de pontos (
sample_angles_deg,sample_ranges_m,sample_reflectivity)
- caminho de relay continua enxuto: receber -> reenviar -> contadores
- interpretacao roda no mesmo processo, mas isolada por tratamento de excecao
- erro de parse nao derruba relay
- servidor web roda em thread separada para nao bloquear o loop UDP
- logs continuam em stdout/stderr
Se o uso de CPU subir com web habilitada:
- mantenha NumPy instalado (sem ele cai para parser Python puro)
- aumente
web.parse_every_n_packets(ex.: 2, 3, 5) - reduza
web.max_sample_points(ex.: 180, 90, 60) - use
web.parse_mode = \"minimal\"para monitoramento leve
python3 scripts/udp_scanner_simulator.py \
--scanner scanner_1,127.0.0.1,21110 \
--hz 30 \
--packets-per-cycle 4 \
--payload-size 512 \
--duration-sec 10Observacao: o simulador nao gera telegrama real do nanoScan3, entao a parte de interpretacao pode nao preencher campos reais.
Use systemd/udp-relay.service como base e ajuste:
User/GroupWorkingDirectoryExecStartcom--config
- exportar metricas em Prometheus
- historico em CSV opcional
- endpoint de health detalhado
- tuning adicional de socket
- suporte multicast opcional