Add rotary phone web interface with multiple greeting support
Features: - Web interface for managing rotary phone system - Support for multiple greeting messages with selector - Direct audio playback in browser for recordings and greetings - Upload multiple WAV files at once - Set active greeting that plays when phone is picked up - HiFiBerry DAC+ADC Pro audio configuration - GPIO-based handset detection and audio recording - Real-time status monitoring with auto-refresh 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
283
test_complete.py
Normal file
283
test_complete.py
Normal file
@@ -0,0 +1,283 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Complete HiFiBerry Test - Verify speaker and microphone work
|
||||
"""
|
||||
|
||||
import pyaudio
|
||||
import wave
|
||||
import numpy as np
|
||||
import time
|
||||
import os
|
||||
|
||||
# HiFiBerry device index (from your system)
|
||||
HIFIBERRY_INDEX = 1
|
||||
SAMPLE_RATE = 44100
|
||||
|
||||
def test_playback():
|
||||
"""Test speaker output"""
|
||||
print("\n" + "="*60)
|
||||
print("🔊 TESTING SPEAKER PLAYBACK")
|
||||
print("="*60)
|
||||
|
||||
audio = pyaudio.PyAudio()
|
||||
|
||||
try:
|
||||
# Show device info
|
||||
info = audio.get_device_info_by_index(HIFIBERRY_INDEX)
|
||||
print(f"\nUsing device: {info['name']}")
|
||||
print(f"Max output channels: {info['maxOutputChannels']}")
|
||||
|
||||
# Generate test tone (440Hz A note)
|
||||
print("\nGenerating 440Hz test tone...")
|
||||
duration = 3
|
||||
t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False)
|
||||
tone = np.sin(2 * np.pi * 440 * t)
|
||||
tone = (tone * 0.3 * 32767).astype(np.int16) # 30% volume
|
||||
|
||||
# Open stream
|
||||
stream = audio.open(
|
||||
format=pyaudio.paInt16,
|
||||
channels=1,
|
||||
rate=SAMPLE_RATE,
|
||||
output=True,
|
||||
output_device_index=HIFIBERRY_INDEX,
|
||||
frames_per_buffer=1024
|
||||
)
|
||||
|
||||
print("🎵 Playing 3-second tone - LISTEN NOW!")
|
||||
print(" You should hear a clear beep from your speaker...")
|
||||
|
||||
# Play
|
||||
chunk_size = 2048
|
||||
for i in range(0, len(tone.tobytes()), chunk_size):
|
||||
stream.write(tone.tobytes()[i:i + chunk_size])
|
||||
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
|
||||
print("✓ Playback completed")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Playback error: {e}")
|
||||
return False
|
||||
finally:
|
||||
audio.terminate()
|
||||
|
||||
def test_recording():
|
||||
"""Test microphone input"""
|
||||
print("\n" + "="*60)
|
||||
print("🎙️ TESTING MICROPHONE RECORDING")
|
||||
print("="*60)
|
||||
|
||||
audio = pyaudio.PyAudio()
|
||||
|
||||
try:
|
||||
# Show device info
|
||||
info = audio.get_device_info_by_index(HIFIBERRY_INDEX)
|
||||
print(f"\nUsing device: {info['name']}")
|
||||
print(f"Max input channels: {info['maxInputChannels']}")
|
||||
|
||||
# Record
|
||||
print("\n🔴 Recording for 5 seconds...")
|
||||
print(" SPEAK NOW or make noise near the microphone...")
|
||||
|
||||
stream = audio.open(
|
||||
format=pyaudio.paInt16,
|
||||
channels=1,
|
||||
rate=SAMPLE_RATE,
|
||||
input=True,
|
||||
input_device_index=HIFIBERRY_INDEX,
|
||||
frames_per_buffer=1024
|
||||
)
|
||||
|
||||
frames = []
|
||||
for i in range(0, int(SAMPLE_RATE / 1024 * 5)):
|
||||
data = stream.read(1024, exception_on_overflow=False)
|
||||
frames.append(data)
|
||||
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
|
||||
print("✓ Recording completed")
|
||||
|
||||
# Save to file
|
||||
filename = "/tmp/test_recording.wav"
|
||||
wf = wave.open(filename, 'wb')
|
||||
wf.setnchannels(1)
|
||||
wf.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
|
||||
wf.setframerate(SAMPLE_RATE)
|
||||
wf.writeframes(b''.join(frames))
|
||||
wf.close()
|
||||
|
||||
print(f"✓ Saved to {filename}")
|
||||
|
||||
# Calculate volume level
|
||||
audio_data = np.frombuffer(b''.join(frames), dtype=np.int16)
|
||||
volume = np.abs(audio_data).mean()
|
||||
max_volume = np.abs(audio_data).max()
|
||||
|
||||
print(f"\nRecording analysis:")
|
||||
print(f" Average level: {volume:.0f}")
|
||||
print(f" Peak level: {max_volume}")
|
||||
|
||||
if max_volume > 1000:
|
||||
print(" ✓ Good signal detected!")
|
||||
else:
|
||||
print(" ⚠️ Very low signal - microphone might not be working")
|
||||
|
||||
audio.terminate()
|
||||
|
||||
# Play back
|
||||
print("\n🔊 Playing back your recording...")
|
||||
audio = pyaudio.PyAudio()
|
||||
|
||||
wf = wave.open(filename, 'rb')
|
||||
stream = audio.open(
|
||||
format=audio.get_format_from_width(wf.getsampwidth()),
|
||||
channels=wf.getnchannels(),
|
||||
rate=wf.getframerate(),
|
||||
output=True,
|
||||
output_device_index=HIFIBERRY_INDEX
|
||||
)
|
||||
|
||||
data = wf.readframes(1024)
|
||||
while data:
|
||||
stream.write(data)
|
||||
data = wf.readframes(1024)
|
||||
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
wf.close()
|
||||
|
||||
print("✓ Playback of recording completed")
|
||||
print(f"\nYou can listen again with: aplay {filename}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Recording error: {e}")
|
||||
return False
|
||||
finally:
|
||||
audio.terminate()
|
||||
|
||||
def test_dial_tone():
|
||||
"""Test classic dial tone (350Hz + 440Hz)"""
|
||||
print("\n" + "="*60)
|
||||
print("📞 TESTING DIAL TONE")
|
||||
print("="*60)
|
||||
|
||||
audio = pyaudio.PyAudio()
|
||||
|
||||
try:
|
||||
print("\nGenerating classic dial tone (350Hz + 440Hz)...")
|
||||
duration = 3
|
||||
t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False)
|
||||
|
||||
# Generate two frequencies
|
||||
tone1 = np.sin(2 * np.pi * 350 * t)
|
||||
tone2 = np.sin(2 * np.pi * 440 * t)
|
||||
tone = (tone1 + tone2) / 2
|
||||
tone = (tone * 0.3 * 32767).astype(np.int16)
|
||||
|
||||
stream = audio.open(
|
||||
format=pyaudio.paInt16,
|
||||
channels=1,
|
||||
rate=SAMPLE_RATE,
|
||||
output=True,
|
||||
output_device_index=HIFIBERRY_INDEX,
|
||||
frames_per_buffer=1024
|
||||
)
|
||||
|
||||
print("🎵 Playing dial tone - This is what you'll hear when picking up the phone!")
|
||||
|
||||
chunk_size = 2048
|
||||
for i in range(0, len(tone.tobytes()), chunk_size):
|
||||
stream.write(tone.tobytes()[i:i + chunk_size])
|
||||
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
|
||||
print("✓ Dial tone playback completed")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Dial tone error: {e}")
|
||||
return False
|
||||
finally:
|
||||
audio.terminate()
|
||||
|
||||
def show_device_info():
|
||||
"""Show all audio devices"""
|
||||
print("\n" + "="*60)
|
||||
print("📋 AUDIO DEVICES ON YOUR SYSTEM")
|
||||
print("="*60)
|
||||
|
||||
audio = pyaudio.PyAudio()
|
||||
|
||||
print("\nAll devices:")
|
||||
for i in range(audio.get_device_count()):
|
||||
info = audio.get_device_info_by_index(i)
|
||||
device_type = []
|
||||
if info['maxOutputChannels'] > 0:
|
||||
device_type.append("OUTPUT")
|
||||
if info['maxInputChannels'] > 0:
|
||||
device_type.append("INPUT")
|
||||
|
||||
marker = " ← USING THIS" if i == HIFIBERRY_INDEX else ""
|
||||
print(f" [{i}] {info['name']}{marker}")
|
||||
print(f" Type: {', '.join(device_type)}")
|
||||
print(f" Sample rate: {info['defaultSampleRate']}")
|
||||
print()
|
||||
|
||||
audio.terminate()
|
||||
|
||||
def main():
|
||||
"""Main test routine"""
|
||||
print("\n" + "="*60)
|
||||
print("🎛️ HIFIBERRY COMPLETE SYSTEM TEST")
|
||||
print("="*60)
|
||||
print(f"\nTesting HiFiBerry at device index: {HIFIBERRY_INDEX}")
|
||||
|
||||
# Show devices
|
||||
show_device_info()
|
||||
|
||||
input("\nPress Enter to start tests...")
|
||||
|
||||
# Test 1: Playback
|
||||
test1 = test_playback()
|
||||
time.sleep(1)
|
||||
|
||||
# Test 2: Dial tone
|
||||
test2 = test_dial_tone()
|
||||
time.sleep(1)
|
||||
|
||||
# Test 3: Recording
|
||||
test3 = test_recording()
|
||||
|
||||
# Summary
|
||||
print("\n" + "="*60)
|
||||
print("📊 TEST SUMMARY")
|
||||
print("="*60)
|
||||
print(f"\n✓ Speaker playback: {'PASS ✓' if test1 else 'FAIL ❌'}")
|
||||
print(f"✓ Dial tone: {'PASS ✓' if test2 else 'FAIL ❌'}")
|
||||
print(f"✓ Microphone recording: {'PASS ✓' if test3 else 'FAIL ❌'}")
|
||||
|
||||
if test1 and test2 and test3:
|
||||
print("\n🎉 ALL TESTS PASSED!")
|
||||
print("\nYour rotary phone system is ready to use!")
|
||||
print("Run: python3 rotary_phone_web.py")
|
||||
else:
|
||||
print("\n⚠️ Some tests failed. Check the output above for details.")
|
||||
|
||||
print("\n" + "="*60)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nTest interrupted by user")
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
Reference in New Issue
Block a user