Skip to content

Commit c11a2c1

Browse files
author
Tom Softreck
committed
update
1 parent c49d9da commit c11a2c1

8 files changed

Lines changed: 198 additions & 73 deletions

File tree

Makefile

Lines changed: 78 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ docker-run: docker
260260
-v $(PWD)/examples:/app/examples \
261261
-v $(PWD)/.env:/app/.env \
262262
dialogchain:latest \
263-
dialogchain run -c examples/simple_routes.yaml
263+
dialogchain run -c examples/simple.yaml
264264

265265
# Examples and setup
266266
setup-env: venv
@@ -280,51 +280,28 @@ setup-env: venv
280280
# List available examples
281281
list-examples:
282282
@echo "Available examples:"
283-
@echo " simple - Basic routing example"
284-
@echo " grpc - gRPC service integration"
285-
@echo " iot - IoT device communication"
286-
@echo " camera - Video processing pipeline"
287-
288-
# Initialize example configurations
289-
init-camera:
290-
poetry run dialogchain init --template camera --output examples/camera_routes.yaml
291-
@echo "✅ Camera configuration template created"
292-
293-
init-grpc:
294-
poetry run dialogchain init --template grpc --output examples/grpc_routes.yaml
295-
@echo "✅ gRPC configuration template created"
296-
297-
init-iot:
298-
poetry run dialogchain init --template iot --output examples/iot_routes.yaml
299-
@echo "✅ IoT configuration template created"
300-
301-
# Run examples
302-
run-example: setup-env
303-
@if [ -z "$(EXAMPLE)" ]; then \
304-
echo "Error: Please specify an example with EXAMPLE=name"; \
305-
echo "Available examples: simple, grpc, iot, camera"; \
306-
exit 1; \
307-
fi
308-
@echo "🚀 Starting $(EXAMPLE) example..."
309-
@case "$(EXAMPLE)" in \
310-
simple) \
311-
poetry run dialogchain run -c examples/simple_config.yaml ;; \
312-
grpc) \
313-
docker-compose -f examples/docker-compose.yml up -d grpc-server && \
314-
poetry run dialogchain run -c examples/grpc_routes.yaml ;; \
315-
iot) \
316-
docker-compose -f examples/docker-compose.yml up -d mosquitto && \
317-
poetry run dialogchain run -c examples/iot_routes.yaml ;; \
318-
camera) \
319-
poetry run dialogchain run -c examples/camera_routes.yaml ;; \
320-
*) \
321-
echo "Error: Unknown example '$(EXAMPLE)'"; \
322-
exit 1 ;; \
323-
esac
283+
@echo " make camera - Run camera processing pipeline"
284+
@echo " make mqtt - Run MQTT example"
285+
@echo " make grpc - Run gRPC example"
286+
287+
# Example targets
288+
camera: setup-env
289+
@echo "🚀 Running camera processing pipeline..."
290+
poetry run dialogchain run -c examples/camera.yaml
291+
292+
rtsp: setup-env
293+
@echo "🚀 Running camera processing pipeline..."
294+
poetry run dialogchain run -c examples/rtsp.yaml
324295

325-
# Run the simple example with verbose output
326-
run-simple-verbose:
327-
poetry run dialogchain run -c examples/simple_config.yaml --verbose
296+
mqtt: setup-env
297+
@echo "🚀 Starting MQTT broker and running IoT example..."
298+
docker-compose -f examples/docker-compose.yml up -d mosquitto
299+
poetry run dialogchain run -c examples/iot.yaml
300+
301+
grpc: setup-env
302+
@echo "🚀 Starting gRPC server and running example..."
303+
docker-compose -f examples/docker-compose.yml up -d grpc-server
304+
poetry run dialogchain run -c examples/grpc.yaml
328305

329306
# View logs for running example
330307
view-logs:
@@ -360,65 +337,93 @@ stop:
360337
@docker-compose -f examples/docker-compose.yml down -v --remove-orphans || true
361338
@echo "✅ All Docker containers stopped and volumes removed"
362339

363-
# Alias for backward compatibility
364-
run-camera: setup-env
365-
@echo "🚀 Running camera processing pipeline..."
366-
@make run-example EXAMPLE=camera
367-
368-
run-grpc: setup-env
369-
@echo "🚀 Running gRPC example..."
370-
@make run-example EXAMPLE=grpc
340+
# Network Configuration
341+
# ====================
342+
343+
# Default network (can be overridden)
344+
DEFAULT_NETWORK ?= 192.168.188.0/24
345+
346+
# Get the default network interface
347+
DEFAULT_IFACE := $(shell ip route | grep '^default' | awk '{print $$5}' | head -1)
348+
349+
# Get the current network from the default interface
350+
CURRENT_NETWORK := $(shell ip -4 -o addr show $(DEFAULT_IFACE) 2>/dev/null | awk '{print $$4}' | cut -d'/' -f1 | sed 's/$$/\/24/')
351+
352+
# Network Information
353+
network-info:
354+
@echo "🔍 Network Information"
355+
@echo "-------------------"
356+
@echo "Interface: $(DEFAULT_IFACE)"
357+
@echo "Local IP: $(shell hostname -I | awk '{print $$1}')"
358+
@echo "Network: $(CURRENT_NETWORK)"
359+
@echo "Gateway: $(shell ip route | grep '^default' | awk '{print $$3}')"
360+
@echo "Using: $(DEFAULT_NETWORK) (DEFAULT_NETWORK)"
361+
362+
# Update .env with current network settings
363+
update-env:
364+
@echo "📝 Updating .env with network settings..."
365+
@if [ -f .env ]; then \
366+
sed -i "s/^DEFAULT_NETWORK=.*/DEFAULT_NETWORK=$(DEFAULT_NETWORK)/" .env; \
367+
else \
368+
echo "DEFAULT_NETWORK=$(DEFAULT_NETWORK)" > .env; \
369+
fi
370+
@echo "✅ Updated .env with DEFAULT_NETWORK=$(DEFAULT_NETWORK)"
371371

372-
run-iot: setup-env
373-
@echo "🚀 Running IoT example..."
374-
@make run-example EXAMPLE=iot
372+
# Get current network (for scripts)
373+
get-network:
374+
@echo "$(DEFAULT_NETWORK)"
375375

376-
# Network scanning scripts
376+
# Network Scanning
377+
# ===============
377378
SCAN_SCRIPT=scripts/network_scanner.py
378379
PRINTER_SCRIPT=scripts/printer_scanner.py
379380

380-
# Common network settings
381-
DEFAULT_NETWORK?=192.168.1.0/24
381+
# Common scanning parameters
382382
COMMON_PORTS=80,443,554,8000-8090,8443,8554,8888,9000-9001,10000-10001
383383
SERVICES=rtsp,http,https,onvif,rtmp,rtmps,rtmpt,rtmpts,rtmpe,rtmpte,rtmfp
384384

385385
# Network scanning targets
386386
.PHONY: scan-network scan-cameras scan-camera scan-printers scan-local scan-quick scan-full scan-local-camera help
387387

388388
## Network scanning
389-
scan-network: ## Scan the default network for common services
389+
scan-network: venv ## Scan the default network for common services
390390
@echo "🔍 Scanning $(DEFAULT_NETWORK) for common services..."
391391
@python3 $(SCAN_SCRIPT) --network $(DEFAULT_NETWORK) --service $(SERVICES) --port $(COMMON_PORTS)
392392

393+
# Network scanner settings
394+
SCAN_PORTS := 80,81,82,83,84,85,86,87,88,89,90,443,554,8000-8100,8443,8554,8888,9000-9010,10000-10010
395+
SCAN_SERVICES := rtsp,http,https,onvif
396+
SCAN_TIMEOUT := 2
397+
393398
## Camera-specific scanning
394-
scan-cameras: ## Scan for cameras and related services
399+
scan-cameras: venv ## Scan for cameras and related services
395400
@echo "📷 Scanning for cameras (RTSP, HTTP, ONVIF, etc.)..."
396-
@python3 $(SCAN_SCRIPT) --network $(DEFAULT_NETWORK) --service $(SERVICES) --port $(COMMON_PORTS) --verbose
401+
@./venv/bin/python $(SCAN_SCRIPT) --network $(DEFAULT_NETWORK) --service $(SCAN_SERVICES) --port $(SCAN_PORTS) --timeout $(SCAN_TIMEOUT) --verbose
397402

398-
scan-camera: ## Scan a specific camera IP (make scan-camera IP=192.168.1.100)
403+
scan-camera: venv ## Scan a specific camera IP (make scan-camera IP=192.168.1.100)
399404
@if [ -z "$(IP)" ]; then echo "❌ Please specify an IP address: make scan-camera IP=192.168.1.100"; exit 1; fi
400405
@echo "🔍 Scanning camera at $(IP)..."
401-
@python3 $(SCAN_SCRIPT) --network $(IP) --service $(SERVICES) --port $(COMMON_PORTS) --verbose
406+
@./venv/bin/python $(SCAN_SCRIPT) --network $(IP) --service $(SCAN_SERVICES) --port $(SCAN_PORTS) --timeout $(SCAN_TIMEOUT) --verbose
402407

403408
## Quick and full network scans
404-
scan-quick: ## Quick scan of common ports (fast but less thorough)
409+
scan-quick: venv ## Quick scan of common ports (fast but less thorough)
405410
@echo "⚡ Quick network scan..."
406-
@python3 $(SCAN_SCRIPT) --network $(DEFAULT_NETWORK) --port 21-23,80,443,554,8000,8080,8081,8443,9000 --timeout 1
411+
@./venv/bin/python $(SCAN_SCRIPT) --network $(DEFAULT_NETWORK) --port 21-23,80,443,554,8000,8080,8081,8443,9000 --timeout 1
407412

408-
scan-full: ## Comprehensive scan (slower but more thorough)
413+
scan-full: venv ## Comprehensive scan (slower but more thorough)
409414
@echo "🔍 Full network scan (this may take a while)..."
410-
@python3 $(SCAN_SCRIPT) --network $(DEFAULT_NETWORK) --port 1-10000 --timeout 2
415+
@./venv/bin/python $(SCAN_SCRIPT) --network $(DEFAULT_NETWORK) --port 1-10000 --timeout 2
411416

412417
## Local network scan (common home network ranges)
413-
scan-local: ## Scan common local network ranges
418+
scan-local: venv ## Scan common local network ranges
414419
@echo "🏠 Scanning common local network ranges..."
415420
@for net in 192.168.0.0/24 192.168.1.0/24 192.168.2.0/24 10.0.0.0/24 10.0.1.0/24; do \
416421
echo "\n📡 Scanning network: $$net"; \
417-
python3 $(SCAN_SCRIPT) --network $$net --service $(SERVICES) --port $(COMMON_PORTS); \
422+
./venv/bin/python $(SCAN_SCRIPT) --network $$net --service $(SCAN_SERVICES) --port $(SCAN_PORTS) --timeout $(SCAN_TIMEOUT); \
418423
done
419424

420425
## Printer management
421-
scan-printers: ## List all available printers
426+
scan-printers: venv ## List all available printers
422427
@echo "🖨️ Listing available printers..."
423428
@python3 $(PRINTER_SCRIPT) list
424429

@@ -466,11 +471,11 @@ run-simple: setup-env
466471
@make run-example EXAMPLE=simple
467472

468473
validate:
469-
poetry run dialogchain validate -c examples/simple_routes.yaml
474+
poetry run dialogchain validate -c examples/simple.yaml
470475
@echo "✅ Configuration validated"
471476

472477
dry-run:
473-
poetry run dialogchain run -c examples/simple_routes.yaml --dry-run
478+
poetry run dialogchain run -c examples/simple.yaml --dry-run
474479
@echo "✅ Dry run completed"
475480

476481
# External processor compilation
File renamed without changes.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ opencv-python = "^4.7.0"
3838
numpy = "^1.21.0"
3939
python-nmap = "^0.7.1"
4040
aiofiles = "^24.1.0"
41+
ultralytics = "^8.3.146"
4142

4243
[tool.poetry.group.dev.dependencies]
4344
black = "^23.0.0"

test_input.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"image": "test"}

ultralytics_processor.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/home/tom/github/dialogchain/python/venv/bin/python
2+
3+
import json
4+
import sys
5+
import time
6+
import numpy as np
7+
from ultralytics import YOLO
8+
import cv2
9+
from datetime import datetime, timedelta
10+
11+
def main():
12+
# Configuration
13+
TARGET_FPS = 1.0 # Process 1 frame per second
14+
TARGET_WIDTH = 640 # Target width for resizing
15+
CONFIDENCE_THRESHOLD = 0.5 # Minimum confidence threshold
16+
17+
# Initialize timing
18+
last_processed = datetime.now()
19+
frame_interval = timedelta(seconds=1.0/TARGET_FPS)
20+
21+
# Load the smallest YOLO model
22+
model = YOLO('yolov8n.pt')
23+
24+
# Warm up the model
25+
dummy_input = np.zeros((TARGET_WIDTH, TARGET_WIDTH, 3), dtype=np.uint8)
26+
_ = model(dummy_input, verbose=False)
27+
28+
frame_count = 0
29+
30+
# Process frames from stdin
31+
while True:
32+
current_time = datetime.now()
33+
34+
# Read frame size (first 8 bytes: width and height as 32-bit integers)
35+
header = sys.stdin.buffer.read(8)
36+
if len(header) != 8:
37+
break
38+
39+
width = int.from_bytes(header[:4], byteorder='little')
40+
height = int.from_bytes(header[4:8], byteorder='little')
41+
42+
# Read frame data (3 channels: BGR)
43+
frame_size = width * height * 3
44+
frame_data = sys.stdin.buffer.read(frame_size)
45+
if len(frame_data) != frame_size:
46+
break
47+
48+
frame_count += 1
49+
50+
# Skip frames to achieve target FPS
51+
if current_time - last_processed < frame_interval:
52+
continue
53+
54+
last_processed = current_time
55+
56+
try:
57+
# Convert to numpy array and reshape
58+
frame = np.frombuffer(frame_data, dtype=np.uint8).reshape((height, width, 3))
59+
60+
# Resize frame to reduce processing time
61+
scale = TARGET_WIDTH / max(width, height)
62+
new_size = (int(width * scale), int(height * scale))
63+
if new_size[0] > 0 and new_size[1] > 0:
64+
frame = cv2.resize(frame, new_size, interpolation=cv2.INTER_LINEAR)
65+
66+
# Run YOLO detection with optimized parameters
67+
results = model(
68+
frame,
69+
conf=CONFIDENCE_THRESHOLD,
70+
imgsz=TARGET_WIDTH,
71+
max_det=10, # Limit max detections
72+
verbose=False,
73+
half=False, # Disable half precision for better compatibility
74+
device='cpu' # Force CPU usage
75+
)
76+
77+
# Extract detections
78+
detections = []
79+
for result in results:
80+
for box in result.boxes:
81+
x1, y1, x2, y2 = box.xyxy[0].tolist()
82+
conf = box.conf.item()
83+
cls = int(box.cls.item())
84+
name = result.names[cls]
85+
86+
# Scale coordinates back to original size
87+
if scale != 1.0:
88+
x1, x2 = x1/scale, x2/scale
89+
y1, y2 = y1/scale, y2/scale
90+
91+
detections.append({
92+
'class': name,
93+
'confidence': float(conf),
94+
'position': {
95+
'x1': x1,
96+
'y1': y1,
97+
'x2': x2,
98+
'y2': y2
99+
}
100+
})
101+
102+
# Output results as JSON
103+
print(json.dumps({
104+
'detections': detections,
105+
'frame_size': {'width': width, 'height': height},
106+
'timestamp': current_time.isoformat(),
107+
'frame_count': frame_count
108+
}), flush=True)
109+
110+
# Clear memory
111+
del frame
112+
113+
except Exception as e:
114+
print(f"Error processing frame: {str(e)}", file=sys.stderr, flush=True)
115+
continue
116+
117+
if __name__ == '__main__':
118+
main()

0 commit comments

Comments
 (0)