source: bell-scheduler/trunk/fuentes/n4d-bellscheduler.install/usr/share/n4d/python-plugins/BellSchedulerManager.py @ 7483

Last change on this file since 7483 was 7483, checked in by jrpelegrina, 17 months ago

WIP in menu indicator to stop the bell

File size: 14.7 KB
Line 
1 
2import os
3import json
4import codecs
5import shutil
6import xmlrpclib as n4dclient
7import ssl
8import zipfile
9
10
11class BellSchedulerManager(object):
12
13        def __init__(self):
14
15                self.config_dir=os.path.expanduser("/etc/bellScheduler/")
16                self.config_file=self.config_dir+"bell_list"
17                self.holiday_token=self.config_dir+"enabled_holiday_token"
18                self.cron_dir="/etc/scheduler/tasks.d/"
19                self.cron_file=os.path.join(self.cron_dir,"BellScheduler")
20
21                self.images_folder="/usr/local/share/bellScheduler/images"
22                self.sounds_folder="/usr/local/share/bellScheduler/sounds"
23                self.media_files_folder="/usr/local/share/bellScheduler/"
24               
25                self.indicator_token_folder="/tmp/.BellScheduler"
26                self.indicator_token_path=os.path.join(self.indicator_token_folder,"bellscheduler-token")
27                self.cmd_create_token='mkdir -p '+self.indicator_token_folder+' && touch '+self.indicator_token_path+' && '
28                self.cmd_remove_token=';rm -f '+self.indicator_token_path
29
30                server='localhost'
31                context=ssl._create_unverified_context()
32                self.n4d = n4dclient.ServerProxy("https://"+server+":9779",context=context,allow_none=True)
33               
34                self._get_n4d_key()
35
36
37        #def __init__   
38
39
40        def _get_n4d_key(self):
41
42                self.n4dkey=''
43                with open('/etc/n4d/key') as file_data:
44                        self.n4dkey = file_data.readlines()[0].strip()
45
46        #def _get_n4d_key
47
48        def _create_conf(self):
49
50                if not os.path.exists(self.config_dir):
51                        os.makedirs(self.config_dir)
52
53                if not os.path.exists(self.images_folder):
54                        os.makedirs(self.images_folder)
55
56                if not os.path.exists(self.sounds_folder):
57                        os.makedirs(self.sounds_folder)         
58               
59                var={}
60                with codecs.open(self.config_file,'w',encoding="utf-8") as f:
61                        json.dump(var,f,ensure_ascii=False)
62                        f.close()
63
64                return {"status":True,"msg":"Configuration file created successfuly"}
65
66        #def create_conf               
67       
68
69        def read_conf(self):
70               
71                if not os.path.exists(self.config_file):
72                        self._create_conf()
73               
74                f=open(self.config_file)
75               
76                try:
77                        self.bells_config=json.load(f)
78                except Exception as e:
79
80                        self.bells_config={}
81                        return {"status":False,"msg":"Unabled to read configuration file :" +str(e),"code":25,"data":self.bells_config}
82
83
84                f.close()       
85
86                return {"status":True,"msg":"Configuration file readed successfuly","code":26,"data":self.bells_config}
87
88        #def read_conf 
89
90        def _get_tasks_from_cron(self):
91
92                cron_tasks={}
93                tmp_tasks={}
94                tasks=self.n4d.get_local_tasks(self.n4dkey,'SchedulerServer')
95               
96                if tasks["status"]:
97
98                        for item in tasks["data"]:
99                                if item=="BellScheduler":
100                                        tmp_tasks=tasks["data"][item]
101
102                        if len(tmp_tasks)>0:
103                                for     item in tmp_tasks:
104                                        key=str(tmp_tasks[item]["BellId"])
105                                        cron_tasks[key]={}
106                                        cron_tasks[key]["CronId"]=item
107               
108                return cron_tasks
109
110        #def _get_tasks_from_cron       
111               
112       
113        def sync_with_cron(self):
114       
115                bell_tasks=self.read_conf()["data"]
116                keys_bells=bell_tasks.keys()
117
118                bells_incron=self._get_tasks_from_cron()
119                keys_cron=bells_incron.keys()
120                changes=0
121
122                if len(keys_cron)>0:
123                        for item in bell_tasks:
124                                if item in keys_cron:
125                                        if bell_tasks[item]["active"]:
126                                                pass
127                                        else:
128                                                changes+=1
129                                                bell_tasks[item]["active"]=True
130                                else:
131                                        if bell_tasks[item]["active"]:
132                                                changes+=1
133                                                bell_tasks[item]["active"]=False
134                                        else:
135                                                pass
136
137                        for item in keys_cron:
138                                if item not in keys_bells:
139                                        result=self._delete_from_cron(item)
140                                        if not result["status"]:
141                                                return {"status":False,"msg":"Unable to clear alarm from cron file","code":37}
142                else:
143                        for item in bell_tasks:
144                                if bell_tasks[item]["active"]:
145                                        changes+=1
146                                        bell_tasks[item]["active"]=False
147                                       
148
149                if changes>0:
150                        self._write_conf(bell_tasks,"BellList")
151
152                return {"status":True,"msg":"Sync with cron sucessfully","data":bell_tasks}     
153                                       
154
155        #def sync_with_cron     
156
157        def _write_conf(self,info,type_list):
158               
159                if type_list=="BellList":
160                        self.bells_config=info
161                        file_to_write=self.config_file
162                        msg="Bell list saved successfuly"
163                else:
164                        file_to_write=self.cron_file
165                        msg="Cron list saved successfuly"
166
167               
168                with codecs.open(file_to_write,'w',encoding="utf-8") as f:
169                        json.dump(info,f,ensure_ascii=False)
170                        f.close()       
171
172                return {"status":True,"msg":msg}       
173
174
175        #def _write_conf       
176
177        def save_changes(self,info,last_change,action):
178               
179                turn_on=False
180                if action !="remove":
181                        if info[last_change]["active"]:
182                                turn_on=True
183                                tasks_for_cron=self._format_to_cron(info,last_change,action)
184                                result=self.n4d.write_tasks(self.n4dkey,'SchedulerServer','local',tasks_for_cron)
185
186                        else:
187                                result=self._delete_from_cron(last_change)
188                else:
189                        result=self._delete_from_cron(last_change)
190
191
192                if result['status']:   
193                        return self._write_conf(info,"BellList")
194                else:
195                        if action=="edit":
196                                return {"status":False,"action":action,"msg":result['data'],"code":19} 
197                        elif action=="add":
198                                return {"status":False,"action":action,"msg":result['data'],"code":20}
199                        elif action=="remove":
200                                return {"status":False,"action":action,"msg":result['data'],"code":21} 
201                        elif action=="active": 
202                                if turn_on:
203                                        return {"status":False,"action":action,"msg":result['data'],"code":22}
204                                else:
205                                        return {"status":False,"action":action,"msg":result['data'],"code":23}
206               
207        #def save_changes                               
208
209        def _get_cron_id(self,last_change):
210
211                cron_tasks=self._get_tasks_from_cron()
212                if len(cron_tasks)>0:
213                        if last_change in cron_tasks.keys():
214                                return {"status":True, "id":cron_tasks[last_change]}
215               
216                return {"status":False,"id":{"CronId":0}}
217
218        # def _get_cron_id     
219       
220        def _delete_from_cron(self,last_change):
221
222                id_to_remove=self._get_cron_id(last_change)
223                cron_id=id_to_remove["id"]["CronId"]
224                delete={"status":True,"data":"0"}
225
226                if id_to_remove["status"]:
227                        delete=self.n4d.remove_task(self.n4dkey,'SchedulerServer','local','BellScheduler',cron_id,'cmd')
228                       
229                return delete
230
231        #def _delete_from_cron 
232       
233        def _format_to_cron(self,info,item,action):
234
235                info_to_cron={}
236
237
238                if action=="edit" or action=="active":
239                        cron_tasks=self._get_tasks_from_cron()
240                        try:
241                                key=cron_tasks[item]["CronId"]
242                        except:
243                                key="0" 
244                else:
245                        key="0"
246                       
247                info_to_cron["BellScheduler"]={}
248                info_to_cron["BellScheduler"][key]={}
249                info_to_cron["BellScheduler"][key]["name"]=info[item]["name"]
250                info_to_cron["BellScheduler"][key]["dom"]="*"
251                info_to_cron["BellScheduler"][key]["mon"]="*" 
252                info_to_cron["BellScheduler"][key]["h"]=str(info[item]["hour"])
253                info_to_cron["BellScheduler"][key]["m"]=str(info[item]["minute"])
254                info_to_cron["BellScheduler"][key]["protected"]=True
255
256                weekdays=info[item]["weekdays"]
257                days=""
258                if weekdays["0"]:
259                        days=days+"1,"
260                if weekdays["1"]:
261                        days=days+"2,"
262                if weekdays["2"]:
263                        days=days+"3,"
264                if weekdays["3"]:
265                        days=days+"4,"
266                if weekdays["4"]:
267                        days=days+"5,"
268
269                if days!="":
270                        days=days[:-1]
271
272                else:
273                        days='*'
274
275                info_to_cron["BellScheduler"][key]["dow"]=days
276                info_to_cron["BellScheduler"][key]["BellId"]=item                               
277
278               
279                sound_option=info[item]["sound"]["option"]
280                sound_path=info[item]["sound"]["path"]
281                duration=info[item]["play"]["duration"]
282
283
284                if duration>0:
285                        fade_out=int(duration)-2
286                        fade_effects='-af aformat=channel_layouts=mono -af afade=in:st=0:d=6,afade=out:st='+str(fade_out)+":d=2"
287                        cmd=self.cmd_create_token+"ffplay -nodisp -autoexit -t "+str(duration)
288                else:
289                        fade_effects='-af aformat=channel_layouts=mono '
290                        cmd=self.cmd_create_token+"ffplay -nodisp -autoexit "
291
292                if sound_option !="url":
293                        if sound_option =="file":
294                                cmd=cmd+' "'+ sound_path +'" '+fade_effects+self.cmd_remove_token
295                        else:
296                                #random_file="$(find"+ " '"+sound_path+"' -type f -print0 | xargs -0 file -i | awk -F ':' '{ if ($2 ~ /audio/ || $2 ~ /video/ ) print $1 }'| shuf -n 1)"
297                                random_file="$(randomaudiofile" + " '"+sound_path+"')"
298                                cmd=cmd+' "'+ random_file + '" '+fade_effects+self.cmd_remove_token
299                                #cmd=cmd+" $(find"+ " '"+sound_path+"' -type f | shuf -n 1) "+fade_effects             
300                else:
301                        cmd=cmd+ " $(youtube-dl -g "+sound_path+ " | sed -n 2p) "+fade_effects+self.cmd_remove_token
302                       
303                info_to_cron["BellScheduler"][key]["cmd"]=cmd
304
305                if os.path.exists(self.holiday_token):
306                        info_to_cron["BellScheduler"][key]["holidays"]=True
307                else:
308                        info_to_cron["BellScheduler"][key]["holidays"]=False
309       
310                       
311                return info_to_cron
312
313        #def _format_to_cron   
314
315        def copy_media_files(self,image,sound):
316
317
318                if image!="":
319                        image_file=os.path.basename(image)
320                        image_dest=os.path.join(self.images_folder,image_file)
321
322                if sound!="":
323                        sound_file=os.path.basename(sound)
324                        sound_dest=os.path.join(self.sounds_folder,sound_file)
325
326                try:
327                        if image!="":
328                                if not os.path.exists(image_dest):
329                                        shutil.copy2(image,image_dest)
330
331                        if sound!="":
332                                if not os.path.exists(sound_dest):
333                                        shutil.copy2(sound,sound_dest)
334
335                        result={"status":True,"msg":"Files copied successfully"}
336                except Exception as e:
337                                result={"status":False,"msg":str(e),"code":24}         
338
339                return result
340       
341        #def copy_media_files
342
343        def export_bells_conf(self,dest_file,user,arg=None):
344
345                tmp_export=tempfile.mkdtemp("_bell_export")
346               
347                try:
348                        shutil.copy2(self.config_file,os.path.join(tmp_export,os.path.basename(self.config_file)))
349                        if os.path.exists(self.cron_file):
350                                shutil.copy2(self.cron_file,os.path.join(tmp_export,os.path.basename(self.cron_file)))
351                        if os.path.exists(self.holiday_token):
352                                shutil.copy2(self.holiday_token,os.path.join(tmp_export,os.path.basename(self.holiday_token)))
353
354                        if os.path.exists(self.media_files_folder):
355                                shutil.copytree(self.media_files_folder,os.path.join(tmp_export,"media"))
356                       
357                        shutil.make_archive(dest_file, 'zip', tmp_export)
358                        if arg!=True:
359                                shutil.rmtree(tmp_export)
360
361                        cmd='chown -R '+user+':'+user +" " + dest_file+'.zip'
362                        os.system(cmd) 
363                        result={"status":True,"msg":"Bells exported successfullly","code":11}
364                                               
365                except Exception as e:
366                        result={"status":False,"msg":str(e),"code":12}         
367
368                return result   
369
370        #def export_bells_conf 
371
372        def import_bells_conf(self,orig_file,user,backup):
373
374                backup_file=["",""]
375                unzip_tmp=tempfile.mkdtemp("_import_bells")
376                result={"status":True}
377                action="disable"
378
379                if backup:
380                        backup_file=tempfile.mkstemp("_bells_backup")
381                        result=self.export_bells_conf(backup_file[1],user,True)
382
383                try:   
384                        if result['status']:   
385                                tmp_zip=zipfile.ZipFile(orig_file)
386                                tmp_zip.extractall(unzip_tmp)
387                                tmp_zip.close   
388
389                                config_file=os.path.join(unzip_tmp,os.path.basename(self.config_file)) 
390                                if os.path.exists(config_file):
391                                        try:
392                                                f=open(config_file)
393                                                read=json.load(f)
394                                                shutil.copy2(config_file,self.config_dir)
395                                                f.close()
396                                        except Exception as e:
397                                                result={"status":False,"msg":str(e),"code":9,"data":backup_file[1]}     
398                                                return result           
399                                                       
400                                cron_file=os.path.join(unzip_tmp,os.path.basename(self.cron_file))
401                                if os.path.exists(cron_file):
402                                        try:
403                                                f=open(cron_file)
404                                                read=json.load(f)
405                                                shutil.copy2(cron_file,self.cron_dir)
406                                                f.close()
407                                                #self.n4d.process_tasks(self.n4dkey,'SchedulerClient')
408                                        except Exception as e:
409                                                result={"status":False,"msg":str(e),"code":9,"data":backup_file[1]}     
410                                                return result   
411
412                                holiday_token=os.path.join(unzip_tmp,os.path.basename(self.holiday_token))     
413                                if os.path.exists(holiday_token):
414                                        action="enable"
415                                        shutil.copyfile(holiday_token,self.holiday_token)       
416                                else:
417                                        if os.path.exists(self.holiday_token):
418                                                os.remove(self.holiday_token)
419
420                                if os.path.exists(self.images_folder):
421                                        shutil.rmtree(self.images_folder)
422                                        shutil.copytree(os.path.join(unzip_tmp,"media/images"),self.images_folder)
423
424                                if os.path.exists(self.sounds_folder):
425                                        shutil.rmtree(self.sounds_folder)
426                                        shutil.copytree(os.path.join(unzip_tmp,"media/sounds"),self.sounds_folder)
427               
428                                update_holiday=self.enable_holiday_control(action)     
429                               
430                                if update_holiday["status"]:   
431                                        result={"status":True,"msg":"Bells imported successfullly","code":10,"data":backup_file[1]}
432                                else:
433                                        result={"status":False,"msg":update_holiday["msg"],"code":9}                           
434                except Exception as e:
435                        result={"status":False,"msg":str(e),"code":9,"data":backup_file[1]}     
436
437               
438                return result           
439
440        #def import_bells_conf
441
442        def enable_holiday_control(self,action):
443
444                result=self._update_holiday_control(action)
445                if result['status']:
446                        if action=="disable":
447                                if os.path.exists(self.holiday_token):
448                                        os.remove(self.holiday_token)   
449                                        result={"status":True,"msg":"Holiday token removed","code":34}
450                        else:
451                                if not os.path.exists(self.holiday_token):
452                                        if not os.path.exists(self.config_dir):
453                                                os.makedirs(self.config_dir)
454                                        f=open(self.holiday_token,'w')
455                                        f.close()
456                                        result={"status":True,"msg":"Holiday token created","code":35}         
457               
458                return result           
459
460        #def enable_holiday
461
462        def _update_holiday_control(self,action):
463
464               
465                if os.path.exists(self.cron_file):
466                        f=open(self.cron_file)
467                        try:
468                                tasks_cron=json.load(f)
469                        except Exception as e:
470                                result={"status":False,"msg":str(e),"code":36}
471                                return result
472
473                       
474                        for item in     tasks_cron["BellScheduler"]:
475                                if action=="enable":
476                                        tasks_cron["BellScheduler"][item]["holidays"]=True
477                               
478                                else:
479                                        tasks_cron["BellScheduler"][item]["holidays"]=False
480
481                       
482                        self._write_conf(tasks_cron,"CronList")
483                        self.n4d.process_tasks(self.n4dkey,'SchedulerClient')
484                        result={"status":True,"msg":"Cron file updated","code":37}
485                else:
486                        result={"status":True,"msg":"Cron file dosn't exists","code":37}                       
487
488                return result
489
490        #def _update_holiday_control           
491
492
493        def update_indicator_control(self):
494
495                if os.path.exists(self.cron_file):
496                        f=open(self.cron_file)
497               
498                        try:
499                                tasks_cron=json.load(f)
500                                f.close()
501                        except Exception as e:
502                                result={"status":False,"msg":str(e),"code":""}
503                                return result
504
505                        for item in tasks_cron["BellScheduler"]:
506                                if not 'bellscheduler_token' in tasks_cron["BellScheduler"][item]["cmd"]:
507                                        tmp_cmd=self.cmd_create_token+tasks_cron["BellScheduler"][item]["cmd"]+self.cmd_remove_token
508                                        tasks_cron["BellScheduler"][item]["cmd"]=tmp_cmd
509
510
511                        self._write_conf(tasks_cron,"CronList")
512                        self.n4d.process_tasks(self.n4dkey,'SchedulerClient')
513                        result={"status":True,"msg":"Cron file updated to use indicator","code":37}
514                else:
515                        result={"status":True,"msg":"Cron file dosn't exists","code":37}                       
516
517                return result
518       
519        #def update_indicator_control
520       
521        def stop_bell(self):
522               
523                cmd='ps -ef | grep "ffplay -nodisp -autoexit" | grep -v "grep"'
524                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
525                output=p.communicate()[0]
526               
527                if type(output) is bytes:
528                        print("decode")
529                        output=output.decode()
530
531                print(output)
532                lst=output.split("\n")
533                lst.pop(0)
534               
535                if len(lst)>0:
536                        for item in lst:
537                                processed_line=item.split(" ")
538                                tmp_list=[]
539                               
540                                if len(processed_line) >= 10:
541                                        for object in processed_line:
542                                                if object!="":
543                                                        tmp_list.append(object)
544                                                        print(tmp_list)
545                                        processed_line=tmp_list
546                       
547                       
548                                        bell_pid=processed_line[1]
549                                        cmd_kill='kill ' +str(bell_pid)
550                                        os.system(cmd_kill)
551                                               
552                                        result={"status":True,"msg":"Alarm stoppped:"+bell_pid,"code":0}
553                                        return result   
554
555        #def stop_bell
556                       
557               
558
559       
Note: See TracBrowser for help on using the repository browser.