Hello,
Je vous sollicite pour savoir si vous avez déjà été confrontés à ce genre de problème : je dispose d’un script python sur une machine PI3B+ distante de mon serveur HA supervised sur PI4. Le github GitHub - kbowman-newedenconsultinggroup/sounddetector sur lequel je m’appuie propose de lancer un service « sounddetector » qui exécute un script python « sounddetector.py »; j’ai bien-sûr fait toutes les déclarations nécessaires pour configurer sounddetector.service
switch:
- platform: mqtt
name: "Sound Detector"
command_topic: "sounddetector/cmds"
state_topic: "sounddetector/state"
payload_on: "systemctl start sounddetector"
payload_off: "systemctl stop sounddetector"
state_off: "offline"
state_on: "online"
icon: mdi:music-note
Le service sounddetector.service est défini de la manière suivante :
[Unit]
After=networking.service
[Service]
User=pi
Group=pi
WorkingDirectory=/home/pi/home/sounddetector
ExecStart=/home/pi/home/sounddetector/sounddetector.py
[Install]
WantedBy=default.target
D’une, transitant via MQTT je me dis que je n’ai pas à passer par un ssh -i /config/.ssh/id_rsa -o StrictHostKeyChecking=no -p 22 pi@192.168.1.32 'sudo systemctl start sounddetector'
De deux, il s’avère que quand j’exécute sur machine distante un « python3 sounddetector.py » je vois bien passer les publications en surveillant le MQTT; mais quand j’exécute un sudo systemctl start sounddetector
je vois bien qu’il démarre sounddetector.py, mais je ne vois aucune publication MQTT arrivée Savez-vous d’où cela peut venir ?
Merci d’avance pour vos aide et conseil
pour info, le code du sounddetector.py ressemble à ça :
#!/usr/bin/env python
#Tone detection shamelessly stolen from:
#https://benchodroff.com/2017/02/18/using-a-raspberry-pi-with-a-microphone-to-hear-an-audio-alarm-using-fft-in-python/
#
# this entire thing stolen from Sufficiently-Advanced (Allen Pan)
#
import pyaudio
from numpy import zeros,linspace,short,frombuffer,hstack,transpose,log
from scipy.fftpack import fft
from time import sleep
from collections import deque
import paho.mqtt.client as mqtt
import requests
import datetime
import time
import sys
import signal
from secrets import mqtthost, mqttuser, mqttpass
def terminateProcess(signalNumber, frame):
client.publish("sounddetector/state", "offline")
sys.exit()
if __name__ == '__main__':
# register the signals to be caught
signal.signal(signal.SIGTERM, terminateProcess)
#mqtt stuff
client = mqtt.Client(client_id="sounddetector")
client.username_pw_set(username=mqttuser,password=mqttpass)
client.connect(mqtthost,1883,300)
#Volume Sensitivity, 0.05: Extremely Sensitive, may give false alarms
# 0.1: Probably Ideal volume
# 1: Poorly sensitive, will only go off for relatively loud
SENSITIVITY= 1
#Bandwidth for detection (i.e., detect frequencies within this margin of error of the TONE)
BANDWIDTH = 10
#How many 46ms blips before we declare a beep? (Take the beep length in ms, divide by 46ms, subtract a bit)
beeplength=5
# How many beeps before we declare a tone?
tonelength=5
# How many false 46ms blips before we declare the alarm is not ringing
resetlength=8
# How many reset counts until we clear an active alarm?
clearlength=10
# Enable blip, beep, and reset debug output
debug=True
# Show the most intense frequency detected (useful for configuration)
frequencyoutput=True
blipcount=0
beepcount=0
resetcount=0
clearcount=0
tone=True
# what devices are we using
if debug:
pd = pyaudio.PyAudio()
info = pd.get_host_api_info_by_index(0)
numdevices = info.get('deviceCount')
for i in range(0, numdevices):
if (pd.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
print ("Input Device id ", i, " - ", pd.get_device_info_by_host_api_device_index(0, i).get('name'))
# Alarm frequencies (Hz) to detect (Use audacity to record a wave and then do Analyze->Plot Spectrum)
D1 = 1260
D2 = 470
F = 940
G = 1130
D5 = 1420
#These numbers work for my ocarina in my house with a blue yeti, ymmv
minD1 = D1-BANDWIDTH
maxD1 = D1+BANDWIDTH
minD2 = D2-BANDWIDTH
maxD2 = D2+BANDWIDTH
minF = F-40
maxF = F+BANDWIDTH
minG = G-BANDWIDTH
maxG = G+BANDWIDTH
minD5 = D5-BANDWIDTH
maxD5 = D5+BANDWIDTH
# Song note sequences
doorbell = deque(['D1','D1','D1','D1','D1','D1'])
test = deque(['D2','F','D2','F','D2','F'])
#heard note sequence deque
notes = deque(['F','F','F','F','F','F'], maxlen=6)
# Show the most intense frequency detected (useful for configuration)
frequencyoutput=True
freqNow = 1.0
freqPast = 1.0
#Set up audio sampler -
NUM_SAMPLES = 1024
SAMPLING_RATE = 44100 #make sure this matches the sampling rate of your mic!
pa = pyaudio.PyAudio()
_stream = pa.open(format=pyaudio.paInt16,
channels=1, rate=SAMPLING_RATE,
input=True,
frames_per_buffer=NUM_SAMPLES)
if debug: print("Alarm detector working. Press CTRL-C to quit.")
client.publish("sounddetector/state", "online")
client.publish("sounddetector/doorbell_detected", "false")
while True:
timeout = 1 # report in to mqtt every 30 seconds
timeout_start = time.time()
client.publish("sounddetector/doorbell_detected", "false")
while time.time() < timeout_start + timeout:
test = 0
if test == 5:
break
test -= 1
while _stream.get_read_available()< NUM_SAMPLES: sleep(0.05)
audio_data = frombuffer(_stream.read(
_stream.get_read_available()), dtype=short)[-NUM_SAMPLES:]
# Each data point is a signed 16 bit number, so we can normalize by dividing 32*1024
normalized_data = audio_data / 32768.0
intensity = abs(fft(normalized_data))[:NUM_SAMPLES//2]
frequencies = linspace(0.0, float(SAMPLING_RATE)//2, num=NUM_SAMPLES//2)
if frequencyoutput:
which = intensity[1:].argmax()+1
# use quadratic interpolation around the max
if which != len(intensity)-1:
y0,y1,y2 = log(intensity[which-1:which+2:])
x1 = (y2 - y0) * .5 / (2 * y1 - y2 - y0)
# find the frequency and output it
#freqPast = freqNow
freqNow = (which+x1)*SAMPLING_RATE/NUM_SAMPLES
else:
freqNow = which*SAMPLING_RATE/NUM_SAMPLES
if debug: print ("\t\t\t\tfreq=",freqNow) #,"\t",freqPast)
# if debug: print ("\t\t\t\tnotes=",notes)
if max(intensity[(frequencies < D1+BANDWIDTH) & (frequencies > D1-BANDWIDTH )]) > max(intensity[(frequencies < D1-1000) & (frequencies > D1-2000)]) + SENSITIVITY:
blipcount+=1
resetcount=0
if debug: print ("\t\tBlip",blipcount)
if (blipcount>=beeplength):
blipcount=0
resetcount=0
beepcount+=1
if debug: print ("\tBeep",beepcount,freqNow)
if (beepcount>=tonelength):
clearcount=0
tone=True
if debug: print ("ToneDetected")
now = datetime.datetime.now()
ringtime="{\"datetime\":\"" + now.strftime("%Y-%m-%d %H:%M:%S") + "\"}"
client.publish("sounddetector/doorbell", ringtime)
client.publish("sounddetector/doorbell_detected", "true")
sleep(1)
beepcount=0
else:
blipcount=0
resetcount+=1
if debug: print ("\t\t\treset",resetcount)
if (resetcount>=resetlength):
resetcount=0
beepcount=0
if tone:
clearcount+=1
if debug: print ("\t\tclear",clearcount)
if clearcount>=clearlength:
clearcount=0
if debug: print ("Tone Too Short - Cleared")
tone=False
client.publish("sounddetector/state", "online")