Infrastructure that works for all the locks' group!
[smartthings-infrastructure.git] / Extractor / ExtractorScript.py
1 import os
2 readyToReturn = 0
3 ToReturn = ""
4 eventList = []
5 eventVarMap = {}
6 capabilityMap = {}
7 app1Capabilities = []
8 app2Capabilities = []
9 app1Subscribe = False
10 app2Subscribe = False
11
12 def GetToken(f):
13         global readyToReturn
14         global ToReturn
15         Skip = ['\n', '\t', ' ']
16         Special = ["(", "\"", ":", ",", "{", "}", ")", "/", "*"]
17         S = ""
18         if (readyToReturn):
19                 readyToReturn = 0
20                 return ToReturn
21         ToReturn = ""
22         c = f.read(1)
23         while(True):
24                 if (c in Special):
25                         if (S != ""):
26                                 readyToReturn = 1
27                                 ToReturn = c
28                                 return S
29                         else:
30                                 return c
31                 elif (c in Skip):
32                         if (S != ""):
33                                 return S        
34                         else:
35                                 c = f.read(1)
36                                 continue
37                 S += c
38                 c = f.read(1)
39                 if not c:
40                         return "EOF"
41
42 def ExtractFunctions(F, appName):
43         global eventList
44         global app1Subscribe
45         global app2Subscribe
46         Temp = GetToken(F)
47         while (Temp != "EOF"):
48                 if (Temp == "def" or Temp == "private"):
49                         Temp = GetToken(F)
50                         if (Temp == "def" or Temp == "private"):
51                                 Temp = GetToken(F)
52                         NameofFunc = Temp
53                         if (GetToken(F) == "("): #We have a function to create object for
54                                 if (appName == "App1"):
55                                         extractedFunctionsApp1.write("//Global Object for functions in subscribe method!\n")    
56                                         extractedFunctionsApp1.write("def %s = this.&" % NameofFunc)
57                                         extractedFunctionsApp1.write("%s\n" % NameofFunc)
58                                 else:
59                                         extractedFunctionsApp2.write("//Global Object for functions in subscribe method!\n")    
60                                         extractedFunctionsApp2.write("def %s = this.&" % NameofFunc)
61                                         extractedFunctionsApp2.write("%s\n" % NameofFunc)
62                 
63                 #Check input capability
64                 if (Temp == "input"):
65                         Temp = GetToken(F) #Get '"'
66                         variable = GetToken(F)
67                         Temp = GetToken(F) #Get '"'
68                         Temp = GetToken(F) #Get ','
69                         Temp = GetToken(F) #Get '"'
70                         Temp = GetToken(F) #Get capability...
71                         capability = Temp
72                         capabilityMap[variable] = capability
73                 
74                 #Check subscribed events
75                 if (Temp == "subscribe"):
76                         if (appName == "App1"):
77                                 app1Subscribe = True
78                         else:
79                                 app2Subscribe = True
80                         Temp = GetToken(F)
81                         if (Temp == "("):
82                                 Temp = GetToken(F)
83                         variable = Temp
84                         while (Temp != "\"" and Temp != "app" and Temp != "location"):
85                                 Temp = GetToken(F)
86                         if Temp == "\"":
87                                 Temp = GetToken(F)
88                         if Temp not in eventList:
89                                 eventList.append(Temp)
90                                 eventVarMap[Temp] = variable
91
92                 #Check and analyze capabilities for physical interaction
93                 AnalyzeCapabilities(Temp, appName, F)
94
95                 Temp = GetToken(F)
96         
97         #Warn if there is a potential for physical interaction
98         AnalyzePhysicalInteraction(app1Capabilities, app2Capabilities)
99         AnalyzePhysicalInteraction(app2Capabilities, app1Capabilities)
100
101
102 def AnalyzeCapabilities(Temp, appName, F):
103                         #Illuminance related
104         if (Temp == "capability.switch" or
105                         Temp == "capability.switchLevel" or
106                         Temp == "capability.illuminanceMeasurement" or
107                         Temp == "capability.colorControl" or
108                         #Motion related
109                         Temp == "capability.motionSensor" or
110                         Temp == "capability.accelerationSensor" or
111                         #Water related
112                         Temp == "capability.valve" or
113                         Temp == "capability.waterSensor" or
114                         #Sound related
115                         Temp == "capability.musicPlayer" or
116                         Temp == "capability.alarm" or
117                         Temp == "capability.speechSynthesis" or
118                         Temp == "capability.soundSensor"):
119                 if (appName == "App1"):
120                         app1Capabilities.append(Temp)
121                 else:
122                         app2Capabilities.append(Temp)
123         if (Temp == "capability"):
124                 Temp = GetToken(F) #Get '"'
125                 Temp = GetToken(F) #Get 'Music'
126                 Temp = Temp + GetToken(F) #Get 'Player'
127                 if (Temp == "MusicPlayer"):
128                         if (appName == "App1"):
129                                 app1Capabilities.append("capability.musicPlayer")
130                         else:
131                                 app2Capabilities.append("capability.musicPlayer")
132                         
133 def AnalyzePhysicalInteraction(app1Capab, app2Capab):
134         #Light
135         if ("capability.illuminanceMeasurement" in app1Capab) and ("capability.switch" in app2Capab or 
136                         "capability.switchLevel" in app2Capab or "capability.colorControl" in app2Capab):
137                 print ("\nWARNING: Potential PHYSICAL CONFLICT (light) detected between App1 and App2!\n")
138         #Motion
139         # TODO: Technically this is not entirely precise since we need to be able to detect that the other app creates motion
140         if ("capability.motionSensor" in app1Capab) or ("capability.accelerationSensor" in app1Capab):
141                 print ("\nWARNING: Potential PHYSICAL CONFLICT (motion) detected between App1 and App2!\n")             
142         #Water
143         if ("capability.waterSensor" in app1Capab) and ("capability.valve" in app2Capab or 
144                         "capability.switch" in app2Capab):
145                 print ("\nWARNING: Potential PHYSICAL CONFLICT (water) detected between App1 and App2!\n")
146         #Sound
147         if ("capability.soundSensor" in app1Capab) and ("capability.musicPlayer" in app2Capab or 
148                         "capability.alarm" in app2Capab or "capability.speechSynthesis" in app2Capab):
149                 print ("\nWARNING: Potential PHYSICAL CONFLICT (sound) detected between App1 and App2!\n")
150
151 def ExtractEvents(extractedEvents):
152         global eventList
153         global eventVarMap
154         global capabilityMap
155         extractedEvents.write("while(true) {\n")
156         extractedEvents.write("\tdef eventNumber = Verify.getInt(0,%d)\n" % (len(eventList) - 1))
157         extractedEvents.write("\tswitch(eventNumber) {\n")
158         for i in range(len(eventList)):
159                 extractedEvents.write("\t\tcase %d:\n" % i)
160                 if eventList[i] == "lock":
161                         event = open("eventSimulator/lockEvent.groovy", "r")
162                         for line in event:
163                                 extractedEvents.write(line)
164                         event.close()
165                 elif eventList[i] == "unlock":
166                         event = open("eventSimulator/unlockEvent.groovy", "r")
167                         for line in event:
168                                 extractedEvents.write(line)
169                         event.close()
170                 elif eventList[i] == "contact.open":
171                         event = open("eventSimulator/contactOpenEvent.groovy", "r")
172                         for line in event:
173                                 extractedEvents.write(line)
174                         event.close()
175                 elif eventList[i] == "contact.closed":
176                         event = open("eventSimulator/contactClosedEvent.groovy", "r")
177                         for line in event:
178                                 extractedEvents.write(line)
179                         event.close()
180                 elif eventList[i] == "nfcTouch":
181                         event = open("eventSimulator/nfcTouchEvent.groovy", "r")
182                         for line in event:
183                                 extractedEvents.write(line)
184                         event.close()
185                 elif eventList[i] == "app": #Case for Touched event
186                         event = open("eventSimulator/appTouchEvent.groovy", "r")
187                         for line in event:
188                                 extractedEvents.write(line)
189                         event.close()
190                 elif eventList[i] == "button":
191                         #Write two events subsequently
192                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,1)\n")
193                         extractedEvents.write("\t\t\tif (event == 0) {\n")
194                         event = open("eventSimulator/buttonPushedEvent.groovy", "r")                    
195                         for line in event:
196                                 extractedEvents.write("\t\t" + line)
197                         event.close()
198                         extractedEvents.write("\t\t\t} else {\n")
199                         event = open("eventSimulator/buttonHeldEvent.groovy", "r")
200                         for line in event:
201                                 extractedEvents.write("\t\t" + line)
202                         event.close()
203                         extractedEvents.write("\t\t\t}\n")
204                 elif eventList[i] == "presence":
205                         #Write two events subsequently
206                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,1)\n")
207                         extractedEvents.write("\t\t\tif (event == 0) {\n")
208                         event = open("eventSimulator/presencePresentEvent.groovy", "r")                 
209                         for line in event:
210                                 extractedEvents.write("\t\t" + line)
211                         event.close()
212                         extractedEvents.write("\t\t\t} else {\n")
213                         event = open("eventSimulator/presenceLeftEvent.groovy", "r")
214                         for line in event:
215                                 extractedEvents.write("\t\t" + line)
216                         event.close()
217                         extractedEvents.write("\t\t\t}\n")
218                 elif eventList[i] == "doorState":
219                         #Write two events subsequently
220                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,1)\n")
221                         extractedEvents.write("\t\t\tif (event == 0) {\n")
222                         event = open("eventSimulator/doorOpenEvent.groovy", "r")                        
223                         for line in event:
224                                 extractedEvents.write("\t\t" + line)
225                         event.close()
226                         extractedEvents.write("\t\t\t} else {\n")
227                         event = open("eventSimulator/doorClosedEvent.groovy", "r")
228                         for line in event:
229                                 extractedEvents.write("\t\t" + line)
230                         event.close()
231                         extractedEvents.write("\t\t\t}\n")
232                 elif eventList[i] == "motion":
233                         #Write two events subsequently
234                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,1)\n")
235                         extractedEvents.write("\t\t\tif (event == 0) {\n")
236                         event = open("eventSimulator/motionActiveEvent.groovy", "r")                    
237                         for line in event:
238                                 extractedEvents.write("\t\t" + line)
239                         event.close()
240                         extractedEvents.write("\t\t\t} else {\n")
241                         event = open("eventSimulator/motionInactiveEvent.groovy", "r")
242                         for line in event:
243                                 extractedEvents.write("\t\t" + line)
244                         event.close()
245                         extractedEvents.write("\t\t\t}\n")
246                 elif eventList[i] == "smoke":
247                         #Write three events subsequently
248                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,2)\n")
249                         extractedEvents.write("\t\t\tif (event == 0) {\n")
250                         event = open("eventSimulator/smokeClearEvent.groovy", "r")                      
251                         for line in event:
252                                 extractedEvents.write("\t\t" + line)
253                         event.close()
254                         extractedEvents.write("\t\t\t} else if (event == 1) {\n")
255                         event = open("eventSimulator/smokeDetectedEvent.groovy", "r")
256                         for line in event:
257                                 extractedEvents.write("\t\t" + line)
258                         event.close()
259                         extractedEvents.write("\t\t\t} else {\n")
260                         event = open("eventSimulator/smokeTestedEvent.groovy", "r")
261                         for line in event:
262                                 extractedEvents.write("\t\t" + line)
263                         event.close()
264                         extractedEvents.write("\t\t\t}\n")
265                 elif eventList[i] == "carbonMonoxide":
266                         #Check which capability
267                         variable = eventVarMap[eventList[i]]
268                         capability = capabilityMap[variable]
269
270                         #Write three events subsequently
271                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,2)\n")
272                         extractedEvents.write("\t\t\tif (event == 0) {\n")                      
273                         if capability == "capability.smokeDetector":
274                                 event = open("eventSimulator/smokeCarbonMonoxideClearEvent.groovy", "r")
275                         elif capability == "capability.carbonMonoxideDetector":
276                                 event = open("eventSimulator/carbonMonoxideClearEvent.groovy", "r")
277                         for line in event:
278                                 extractedEvents.write("\t\t" + line)
279                         event.close()
280                         extractedEvents.write("\t\t\t} else if (event == 1) {\n")
281                         if capability == "capability.smokeDetector":
282                                 event = open("eventSimulator/smokeCarbonMonoxideDetectedEvent.groovy", "r")
283                         elif capability == "capability.carbonMonoxideDetector":
284                                 event = open("eventSimulator/carbonMonoxideDetectedEvent.groovy", "r")
285                         for line in event:
286                                 extractedEvents.write("\t\t" + line)
287                         event.close()
288                         extractedEvents.write("\t\t\t} else {\n")
289                         if capability == "capability.smokeDetector":
290                                 event = open("eventSimulator/smokeCarbonMonoxideTestedEvent.groovy", "r")
291                         elif capability == "capability.carbonMonoxideDetector":
292                                 event = open("eventSimulator/carbonMonoxideTestedEvent.groovy", "r")
293                         for line in event:
294                                 extractedEvents.write("\t\t" + line)
295                         event.close()
296                         extractedEvents.write("\t\t\t}\n")
297                 elif eventList[i] == "battery":
298                         event = open("eventSimulator/batteryChargeEvent.groovy", "r")
299                         for line in event:
300                                 extractedEvents.write(line)
301                         event.close()
302                 elif eventList[i] == "thermostatMode":
303                         #Write five events subsequently
304                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,4)\n")
305                         extractedEvents.write("\t\t\tif (event == 0) {\n")
306                         event = open("eventSimulator/thermostatAutoModeEvent.groovy", "r")                      
307                         for line in event:
308                                 extractedEvents.write("\t\t" + line)
309                         event.close()
310                         extractedEvents.write("\t\t\t} else if (event == 1) {\n")
311                         event = open("eventSimulator/thermostatCoolModeEvent.groovy", "r")
312                         for line in event:
313                                 extractedEvents.write("\t\t" + line)
314                         event.close()
315                         extractedEvents.write("\t\t\t} else if (event == 2) {\n")
316                         event = open("eventSimulator/thermostatEmergencyHeatModeEvent.groovy", "r")
317                         for line in event:
318                                 extractedEvents.write("\t\t" + line)
319                         event.close()
320                         extractedEvents.write("\t\t\t} else if (event == 3) {\n")
321                         event = open("eventSimulator/thermostatHeatModeEvent.groovy", "r")
322                         for line in event:
323                                 extractedEvents.write("\t\t" + line)
324                         event.close()
325                         extractedEvents.write("\t\t\t} else {\n")
326                         event = open("eventSimulator/thermostatOffModeEvent.groovy", "r")
327                         for line in event:
328                                 extractedEvents.write("\t\t" + line)
329                         event.close()
330                         extractedEvents.write("\t\t\t}\n")
331                 elif eventList[i] == "switch":
332                         #Write two events subsequently
333                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,1)\n")
334                         extractedEvents.write("\t\t\tif (event == 0) {\n")
335                         event = open("eventSimulator/switchOnEvent.groovy", "r")                        
336                         for line in event:
337                                 extractedEvents.write("\t\t" + line)
338                         event.close()
339                         extractedEvents.write("\t\t\t} else {\n")
340                         event = open("eventSimulator/switchOffEvent.groovy", "r")
341                         for line in event:
342                                 extractedEvents.write("\t\t" + line)
343                         event.close()
344                         extractedEvents.write("\t\t\t}\n")
345                 elif eventList[i] == "location": #Case for Location event
346                         #Write three events subsequently
347                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,2)\n")
348                         extractedEvents.write("\t\t\tif (event == 0) {\n")
349                         event = open("eventSimulator/locationHomeEvent.groovy", "r")                    
350                         for line in event:
351                                 extractedEvents.write("\t\t" + line)
352                         event.close()
353                         extractedEvents.write("\t\t\t} else if (event == 1) {\n")
354                         event = open("eventSimulator/locationAwayEvent.groovy", "r")
355                         for line in event:
356                                 extractedEvents.write("\t\t" + line)
357                         event.close()
358                         extractedEvents.write("\t\t\t} else {\n")
359                         event = open("eventSimulator/locationNightEvent.groovy", "r")
360                         for line in event:
361                                 extractedEvents.write("\t\t" + line)
362                         event.close()
363                         extractedEvents.write("\t\t\t}\n")
364                 elif eventList[i] == "acceleration":
365                         #Write two events subsequently
366                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,1)\n")
367                         extractedEvents.write("\t\t\tif (event == 0) {\n")
368                         event = open("eventSimulator/accelerationActiveEvent.groovy", "r")                      
369                         for line in event:
370                                 extractedEvents.write("\t\t" + line)
371                         event.close()
372                         extractedEvents.write("\t\t\t} else {\n")
373                         event = open("eventSimulator/accelerationInactiveEvent.groovy", "r")
374                         for line in event:
375                                 extractedEvents.write("\t\t" + line)
376                         event.close()
377                         extractedEvents.write("\t\t\t}\n")
378                 elif eventList[i] == "beacon":
379                         #Write two events subsequently
380                         extractedEvents.write("\t\t\tdef event = Verify.getInt(0,1)\n")
381                         extractedEvents.write("\t\t\tif (event == 0) {\n")
382                         event = open("eventSimulator/beaconPresenceEvent.groovy", "r")                  
383                         for line in event:
384                                 extractedEvents.write("\t\t" + line)
385                         event.close()
386                         extractedEvents.write("\t\t\t} else {\n")
387                         event = open("eventSimulator/beaconLeftEvent.groovy", "r")
388                         for line in event:
389                                 extractedEvents.write("\t\t" + line)
390                         event.close()
391                         extractedEvents.write("\t\t\t}\n")
392                 elif eventList[i] == "color":
393                         event = open("eventSimulator/colorChangeEvent.groovy", "r")
394                         for line in event:
395                                 extractedEvents.write(line)
396                         event.close()
397                 elif eventList[i] == "hue":
398                         event = open("eventSimulator/hueChangeEvent.groovy", "r")
399                         for line in event:
400                                 extractedEvents.write(line)
401                         event.close()
402                 elif eventList[i] == "saturation":
403                         event = open("eventSimulator/saturationChangeEvent.groovy", "r")
404                         for line in event:
405                                 extractedEvents.write(line)
406                         event.close()
407
408                 ###TODO: Add more events later
409                 extractedEvents.write("\t\t\tbreak\n")
410         extractedEvents.write("\t}\n")
411         extractedEvents.write("}\n")
412         
413 def CheckIfOnlyTouchEvents():
414         #Check and throw an error if it is all touch events
415         #This is called Direct-Direct interaction and we do not model-check for this case
416         onlyTouchEvents = True
417         for item in eventList:
418                 if item != "nfcTouch" and item != "app":
419                         onlyTouchEvents = False
420         if onlyTouchEvents is True and app1Subscribe is True and app2Subscribe is True:
421                 raise Exception("\n\nDirect-Direct Interaction detected: we are skipping this pair...\n\n")
422
423
424 #Extract objects to call functions from App1
425 F1 = open("Extractor/App1/App1.groovy", "r")
426 extractedFunctionsApp1 = open("Extractor/App1/extractedFunctionsApp1.groovy", "w+")
427 ExtractFunctions(F1, "App1")
428 F1.close()
429
430 #Extract objects to call functions from App2
431 F2 = open("Extractor/App2/App2.groovy", "r")
432 extractedFunctionsApp2 = open("Extractor/App2/extractedFunctionsApp2.groovy", "w+")
433 ExtractFunctions(F2, "App2")
434 F2.close()
435
436 #Prepare eventSimulator file while parsing the App1 and App2 files
437 extractedEvents = open("eventSimulator/eventSimulator.groovy", "w+")
438 CheckIfOnlyTouchEvents()
439 ExtractEvents(extractedEvents)
440 extractedEvents.close()
441
442 #Save the extracted methods and app1 in a same file to extract information
443 extractorFile = open("Extractor/extractorFile.groovy", "w+")
444 Extractor = open("Extractor/Extractor.groovy", "r")
445 F1 = open("Extractor/App1/App1.groovy", "r")
446
447 extractorFile.write("////////////////////\n")
448 extractorFile.write("@Field App\n")
449 extractorFile.write("App = \"App1\"")
450 extractorFile.write("\n")
451 for line in Extractor:
452         extractorFile.write(line)
453 extractorFile.write("\n\n")
454 for line in F1:
455         extractorFile.write(line)
456 extractorFile.close()
457 Extractor.close()
458 F1.close()
459 #Run the file to extract the objects
460 os.system("groovy -classpath lib/jpf.jar Extractor/extractorFile.groovy")
461
462
463 #Save the extracted methods and app2 in a same file to extract information
464 extractorFile = open("Extractor/extractorFile.groovy", "w+")
465 Extractor = open("Extractor/Extractor.groovy", "r")
466 F2 = open("Extractor/App2/App2.groovy", "r")
467
468 extractorFile.write("////////////////////\n")
469 extractorFile.write("@Field App\n")
470 extractorFile.write("App = \"App2\"")
471 extractorFile.write("\n")
472 for line in Extractor:
473         extractorFile.write(line)
474 extractorFile.write("\n\n")
475 for line in F2:
476         extractorFile.write(line)
477 #Run the file to extract the objects
478 extractorFile.close()
479 Extractor.close()
480 F2.close()
481 os.system("groovy -classpath lib/jpf.jar Extractor/extractorFile.groovy")
482
483