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