3 PyAudio example: Record a few seconds of audio and save to a WAVE
14 PARAMFILE = '/var/lib/ampy/params.json'
15 FORMAT = pyaudio.paInt32 # Format
16 STRUCTFORMAT = 'i' # Format for python struct module
20 VOLUME_CONSTANT = 132360.98315789475
22 # https://www.actutem.com/valeur-crete-moyenne-et-efficace-dune-tension-ac/
23 # math.pi/math.sqrt(2)/2 = 1.1107207345395915
25 # Pour 30 A à 230V ( 6900 W )
26 # abs(Sndmax) = 2147483520
27 # Sndavg = 2147483520/math.pi = 683565234.8327662
28 # Sndeff = 683565234.8327662 * 1.1107207345395915 = 759250079.7391784
30 # https://fr.wikipedia.org/wiki/Compteur_%C3%A9lectrique
31 # Mon compteur tourne à une vitesse proportionnelle à la puissance instantanée
33 # https://fr.wikipedia.org/wiki/%C3%89lectricit%C3%A9_domestique#Tension
34 # En france, ERDF fourni 230V EFFICACES (=> 207.0727527161344 moyenne)
36 # raw average: 636207384.4738322 - min: -2147483648 - max: 2147483392
40 def read_params_file():
41 with open(PARAMFILE) as f:
42 params = json.loads(f.read())
46 def loop(optrecord, optstats):
48 params = read_params_file()
49 alsadevice = params['alsadevice']
50 except (FileNotFoundError, json.decoder.JSONDecodeError, KeyError):
51 print("Error reading the parameters. Please run device.py")
54 print("PyAudio opened")
56 print("Ampy Selected input device #{}: {}".format(
57 alsadevice, p.get_device_info_by_index(alsadevice)['name']))
59 NSAMPLE = int(RATE * RECORD_SECONDS)
62 channels=1, # Our ampmeter always returns 0 on the second channel
65 input_device_index=alsadevice)
67 structformat = '<' + STRUCTFORMAT * NSAMPLE
73 data = stream.read(NSAMPLE, exception_on_overflow=False)
74 values = struct.unpack(structformat, data)
76 # for x in range(100):
77 # print('**{:04x}**{}**'.format(values[x], values[x]))
87 avg = float(total) / NSAMPLE
89 print("raw average: {} - min: {} - max: {}".format(
90 avg, minvalue, maxvalue))
91 watts = avg / VOLUME_CONSTANT
92 print("average {:.1f}W ".format(watts), end='\r')
95 "rrdtool update --daemon /var/run/rrdcached.sock"
96 " /var/lib/rrdcached/db/power.rrd {}:{}".format(
98 except KeyboardInterrupt:
99 print("Received KeyboardInterrupt: exiting")
110 parser = argparse.ArgumentParser(description='Ammeter processing')
115 help='Dump recording level stats for every chunk',
119 action='store_false',
121 help='Disable recording in RRD file',
124 args = parser.parse_args()
127 print('Recording disabled.')
129 loop(optrecord=args.record, optstats=args.stats)
132 if __name__ == '__main__':