36
36
ASOUND = '/etc/asound.conf'
37
37
TEMP = Path ('/tmp/service' )
38
38
ALLOWED_LANGUAGES = {'en' , 'de' , 'fr' , 'it' , 'pt' , 'pl' }
39
+ FALLBACK_ASR = 'coqui'
39
40
40
41
41
42
class InitDict (dict ):
@@ -46,40 +47,46 @@ def __init__(self, default: dict):
46
47
47
48
def __getitem__ (self , item ):
48
49
try :
49
- item = super ().__getitem__ (item )
50
- if not item :
50
+ value = super ().__getitem__ (item )
51
+ if value is None :
51
52
raise Exception
52
- return item
53
+ return value
53
54
except :
54
55
print (f'Missing key **{ item } ** in provided yaml file.' )
55
56
return ''
56
57
57
58
58
- class SimpleLogger :
59
+ class SimpleLogger ( object ) :
59
60
60
61
def __init__ (self , prepend : str = None ):
61
- self ._prepend = f'[{ prepend } ]\t '
62
+ self ._prepend = f'[{ prepend } ]'
62
63
self ._logger = logging .getLogger ('ProjectAlice' )
63
64
64
65
65
66
def logInfo (self , text : str ):
66
- self ._logger .info (f'{ self ._prepend } { text } ' )
67
+ self ._logger .info (f'{ self .spacer ( text ) } ' )
67
68
68
69
69
70
def logWarning (self , text : str ):
70
- self ._logger .warning (f'{ self ._prepend } { text } ' )
71
+ self ._logger .warning (f'{ self .spacer ( text ) } ' )
71
72
72
73
73
74
def logError (self , text : str ):
74
- self ._logger .error (f'{ self ._prepend } { text } ' )
75
+ self ._logger .error (f'{ self .spacer ( text ) } ' )
75
76
76
77
77
78
def logFatal (self , text : str ):
78
- self ._logger .fatal (f'{ self ._prepend } { text } ' )
79
+ self ._logger .fatal (f'{ self .spacer ( text ) } ' )
79
80
exit (1 )
80
81
81
82
82
- class PreInit :
83
+ def spacer (self , msg : str ) -> str :
84
+ space = '' .join ([' ' for _ in range (35 - len (self ._prepend ) + 1 )])
85
+ msg = f'{ self ._prepend } { space } { msg } '
86
+ return msg
87
+
88
+
89
+ class PreInit (object ):
83
90
"""
84
91
Pre init checks and makes sure vital stuff is installed and running. Not much, but internet, venv and so on
85
92
Pre init is meant to run on the system python and not on the venv
@@ -209,7 +216,7 @@ def doUpdates(self):
209
216
updateSource = self .getUpdateSource (updateChannel )
210
217
# Update our system and sources
211
218
subprocess .run (['sudo' , 'apt-get' , 'update' ])
212
- # subprocess.run(['sudo', 'apt-get', 'dist-upgrade', '-y'])
219
+ subprocess .run (['sudo' , 'apt-get' , 'dist-upgrade' , '-y' ])
213
220
subprocess .run (['sudo' , 'apt' , 'autoremove' , '-y' ])
214
221
subprocess .run (['git' , 'clean' , '-df' ])
215
222
subprocess .run (['git' , 'stash' ])
@@ -316,7 +323,7 @@ def checkVenv(self) -> bool:
316
323
if not Path ('venv' ).exists ():
317
324
self ._logger .logInfo ('Not running with venv, I need to create it' )
318
325
subprocess .run (['sudo' , 'apt-get' , 'install' , 'python3-dev' , 'python3-pip' , 'python3-venv' , 'python3-wheel' , '-y' ])
319
- subprocess .run (['python3' , '-m' , 'venv' , 'venv' ])
326
+ subprocess .run (['python3.7 ' , '-m' , 'venv' , 'venv' ])
320
327
self .updateVenv ()
321
328
self ._logger .logInfo ('Installed virtual environement, restarting...' )
322
329
return False
@@ -331,7 +338,7 @@ def checkVenv(self) -> bool:
331
338
def updateVenv (self ):
332
339
subprocess .run ([self .PIP , 'uninstall' , '-y' , '-r' , str (Path (self .rootDir , 'pipuninstalls.txt' ))])
333
340
subprocess .run ([self .PIP , 'install' , 'wheel' ])
334
- subprocess .run ([self .PIP , 'install' , '-r' , str (Path (self .rootDir , 'requirements.txt' ))])
341
+ subprocess .run ([self .PIP , 'install' , '-r' , str (Path (self .rootDir , 'requirements.txt' )), '--upgrade' , '--no-cache-dir' ])
335
342
336
343
337
344
@staticmethod
@@ -355,7 +362,7 @@ def setServiceFileTo(pointer: str):
355
362
time .sleep (1 )
356
363
357
364
358
- class Initializer :
365
+ class Initializer ( object ) :
359
366
PIP = './venv/bin/pip'
360
367
361
368
@@ -396,7 +403,7 @@ def initProjectAlice(self) -> bool: # NOSONAR
396
403
self ._logger .logFatal ('Unfortunately it won\' t be possible, config sample is not existing' )
397
404
return False
398
405
399
- self ._confsFile .write_text (json . dumps ( self ._confsSample .read_text (), indent = ' \t ' ))
406
+ self ._confsFile .write_text (self ._confsSample .read_text ())
400
407
401
408
try :
402
409
confs = json .loads (self ._confsFile .read_text ())
@@ -427,6 +434,10 @@ def initProjectAlice(self) -> bool: # NOSONAR
427
434
subprocess .run (['sudo' , 'systemctl' , 'stop' , 'mosquitto' ])
428
435
subprocess .run ('sudo sed -i -e \' s/persistence true/persistence false/\' /etc/mosquitto/mosquitto.conf' .split ())
429
436
subprocess .run (['sudo' , 'rm' , '/var/lib/mosquitto/mosquitto.db' ])
437
+ subprocess .run (['sudo' , 'systemctl' , 'start' , 'mosquitto' ])
438
+
439
+ subprocess .run (['sudo' , 'systemctl' , 'stop' , 'nginx' ])
440
+ subprocess .run (['sudo' , 'systemctl' , 'disable' , 'nginx' ])
430
441
431
442
# Now let's dump some values to their respective places
432
443
# First those that need some checks and self filling in case unspecified
@@ -435,20 +446,20 @@ def initProjectAlice(self) -> bool: # NOSONAR
435
446
436
447
pinCode = initConfs ['adminPinCode' ]
437
448
try :
438
- pin = int (pinCode )
439
- if len (str (pin )) != 4 :
449
+ if len (str (pinCode )) != 4 :
440
450
raise Exception
451
+ int (pinCode )
441
452
except :
442
453
self ._logger .logFatal ('Pin code must be 4 digits' )
443
454
444
- confs ['adminPinCode' ] = int ( pinCode )
455
+ confs ['adminPinCode' ] = pinCode
445
456
446
457
confs ['stayCompletelyOffline' ] = bool (initConfs ['stayCompletelyOffline' ] or False )
447
458
if confs ['stayCompletelyOffline' ]:
448
459
confs ['keepASROffline' ] = True
449
460
confs ['keepTTSOffline' ] = True
450
461
confs ['skillAutoUpdate' ] = False
451
- confs ['asr' ] = 'deepspeech'
462
+ confs ['asr' ] = FALLBACK_ASR
452
463
confs ['tts' ] = 'pico'
453
464
confs ['awsRegion' ] = ''
454
465
confs ['awsAccessKey' ] = ''
@@ -462,14 +473,14 @@ def initProjectAlice(self) -> bool: # NOSONAR
462
473
confs ['awsAccessKey' ] = initConfs ['awsAccessKey' ]
463
474
confs ['awsSecretKey' ] = initConfs ['awsSecretKey' ]
464
475
465
- confs ['asr' ] = initConfs ['asr' ] if initConfs ['asr' ] in {'pocketsphinx' , 'google' , 'deepspeech' , 'snips' , 'coqui' } else 'deepspeech'
476
+ confs ['asr' ] = initConfs ['asr' ] if initConfs ['asr' ] in {'pocketsphinx' , 'google' , 'deepspeech' , 'snips' , 'coqui' } else FALLBACK_ASR
466
477
if confs ['asr' ] == 'google' and not initConfs ['googleServiceFile' ]:
467
- self ._logger .logInfo ('You cannot use Google Asr without a google service file, falling back to Deepspeech ' )
468
- confs ['asr' ] = 'deepspeech'
478
+ self ._logger .logInfo (f 'You cannot use Google Asr without a google service file, falling back to { FALLBACK_ASR } ' )
479
+ confs ['asr' ] = FALLBACK_ASR
469
480
470
481
if confs ['asr' ] == 'snips' and confs ['activeLanguage' ] != 'en' :
471
- self ._logger .logInfo ('You can only use Snips Asr for english, falling back to Deepspeech ' )
472
- confs ['asr' ] = 'deepspeech'
482
+ self ._logger .logInfo (f 'You can only use Snips Asr for english, falling back to { FALLBACK_ASR } ' )
483
+ confs ['asr' ] = FALLBACK_ASR
473
484
474
485
if initConfs ['googleServiceFile' ]:
475
486
googleCreds = Path (self ._rootDir , 'credentials/googlecredentials.json' )
@@ -519,6 +530,7 @@ def initProjectAlice(self) -> bool: # NOSONAR
519
530
try :
520
531
import pkg_resources
521
532
533
+ self ._logger .logInfo ("*** Trying to load SNIPS-NLU." )
522
534
pkg_resources .require ('snips-nlu' )
523
535
subprocess .run (['./venv/bin/snips-nlu' , 'download' , confs ['activeLanguage' ]])
524
536
except :
@@ -557,48 +569,50 @@ def initProjectAlice(self) -> bool: # NOSONAR
557
569
confs ['disableSound' ] = False
558
570
confs ['disableCapture' ] = False
559
571
572
+ hlcDir = Path ('/home' , getpass .getuser (), 'HermesLedControl' )
560
573
hlcServiceFilePath = Path ('/etc/systemd/system/hermesledcontrol.service' )
561
- hlcConfigFilePath = Path (f'/home/{ getpass .getuser ()} /hermesLedControl/configuration.yml' )
574
+ hlcDistributedServiceFilePath = hlcDir / 'hermesledcontrol.service'
575
+ hlcConfigTemplatePath = hlcDir / 'configuration.yml'
562
576
hlcConfig = dict ()
563
577
if initConfs ['useHLC' ]:
564
-
565
- hlcDir = Path ('/home' , getpass .getuser (), 'hermesLedControl' )
578
+ self ._logger .logInfo ("*** Taking care of HLC." )
566
579
567
580
if not hlcDir .exists ():
568
- subprocess .run (['git' , 'clone' , 'https://github.com/project-alice-assistant/hermesLedControl.git' , str (Path ('/home' , getpass .getuser (), 'hermesLedControl' ))])
581
+ #todo: replace with AliceGit maybe?
582
+ subprocess .run (['git' , 'clone' , 'https://github.com/project-alice-assistant/hermesLedControl.git' , str (hlcDir )])
569
583
else :
570
584
subprocess .run (['git' , '-C' , hlcDir , 'stash' ])
571
585
subprocess .run (['git' , '-C' , hlcDir , 'pull' ])
572
586
subprocess .run (['git' , '-C' , hlcDir , 'stash' , 'clear' ])
573
587
574
588
if hlcServiceFilePath .exists ():
575
589
subprocess .run (['sudo' , 'systemctl' , 'stop' , 'hermesledcontrol' ])
590
+ subprocess .run (['sudo' , 'systemctl' , 'disable' , 'hermesledcontrol' ])
576
591
subprocess .run (['sudo' , 'rm' , hlcServiceFilePath ])
577
592
578
- subprocess .run (['python3' , '-m' , 'venv' , f'/home/{ getpass .getuser ()} /hermesLedControl/venv' ])
579
-
580
- reqs = [
581
- 'RPi.GPIO' ,
582
- 'spidev' ,
583
- 'gpiozero' ,
584
- 'paho-mqtt' ,
585
- 'numpy' ,
586
- 'pyyaml'
587
- ]
588
- for req in reqs :
589
- subprocess .run ([f'/home/{ getpass .getuser ()} /hermesLedControl/venv/bin/pip' , 'install' , req ])
593
+ subprocess .run (['python3.7' , '-m' , 'venv' , f'{ str (hlcDir )} /venv' ])
594
+ subprocess .run ([f'{ str (hlcDir )} /venv/bin/pip' , 'install' , '-r' , f'{ str (hlcDir )} /requirements.txt' , '--no-cache-dir' ])
590
595
591
596
import yaml
592
597
593
598
try :
594
- hlcConfig = yaml .safe_load (hlcConfigFilePath .read_text ())
599
+ hlcConfig = yaml .safe_load (hlcConfigTemplatePath .read_text ())
595
600
except yaml .YAMLError as e :
596
- self ._logger .logFatal (f'Failed loading HLC configurations: { e } ' )
597
- else :
598
- hlcConfig ['engine' ] = 'projectalice'
599
- hlcConfig ['pathToConfig' ] = f'/home/{ getpass .getuser ()} /ProjectAlice/config.json'
600
- hlcConfig ['pattern' ] = 'projectalice'
601
- hlcConfig ['enableDoA' ] = False
601
+ self ._logger .logWarning (f'Failed loading HLC configurations - creating new: { e } ' )
602
+ hlcConfig = dict ()
603
+
604
+ hlcConfig ['engine' ] = 'projectalice'
605
+ hlcConfig ['pathToConfig' ] = f'/home/{ getpass .getuser ()} /ProjectAlice/config.json'
606
+ hlcConfig ['pattern' ] = 'projectalice'
607
+ hlcConfig ['enableDoA' ] = False
608
+
609
+ serviceFile = hlcDistributedServiceFilePath .read_text ()
610
+ serviceFile = serviceFile .replace ('%WORKING_DIR%' , f'{ str (hlcDir )} ' )
611
+ serviceFile = serviceFile .replace ('%EXECSTART%' , f'WorkingDirectory={ str (hlcDir )} /venv/bin/python main.py --hermesLedControlConfig=/home/{ getpass .getuser ()} /.config/HermesLedControl/configuration.yml' )
612
+ serviceFile = serviceFile .replace ('%USER%' , f'User={ getpass .getuser ()} ' )
613
+ hlcDistributedServiceFilePath .write_text (serviceFile )
614
+ subprocess .run (['sudo' , 'cp' , hlcDistributedServiceFilePath , hlcServiceFilePath ])
615
+
602
616
603
617
useFallbackHLC = False
604
618
if initConfs ['installSound' ]:
0 commit comments