-
Notifications
You must be signed in to change notification settings - Fork 1
/
command_sequences.py
254 lines (191 loc) · 8.48 KB
/
command_sequences.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# Copyright 2018 Calum Loudon
#
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
# use this file except in compliance with the License. A copy of the License
# is located at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, express or implied. See the License for the specific
# language governing permissions and limitations under the License.
# This file takes a definition of a user's devices and from them constructs a
# set of activities.
import pprint
from logutilities import log_info, log_debug
from alexaSchema import CAPABILITY_DISCOVERY_RESPONSES, CAPABILITY_DIRECTIVES_TO_COMMANDS
from utilities import get_repeats
pp = pprint.PrettyPrinter(indent=2, width = 200)
def which_capability(capability):
# Cope with the 'fake' DevicePowerController capability
if capability == "DevicePowerController":
cap_to_check = "PowerController"
else:
cap_to_check = capability
return cap_to_check
def construct_specific_IR_command(device_details, command, target, device_name, device_logname):
output_cmd = {
'KIRA': device_details['IRcodes'][command],
'protocol': device_details['protocol'],
'target': target,
'repeats': get_repeats(device_details),
'device': device_name,
'log': "Send " + command + " to " + device_logname + " (" + device_name + ")"
}
return output_cmd
def SingleIRCommand(device, capability, command_list):
log_debug("Have list of single IR commands to check: %s", pp.pformat(command_list))
cap_to_check = which_capability(capability)
log_debug("Checking for capability %s", capability)
device_name = device['friendly_name']
device_logname = device['log_name']
device_details = device['details']
target = device['target']
output_cmd = {}
log_debug("Checking device details: %s", pp.pformat(device_details))
if cap_to_check in device_details['supports']:
log_debug("Device %s supports the %s capability", device_name, capability)
output_cmd['SingleIRCommand'] = {}
found = False
for command in command_list:
if not found:
log_debug("Look for command %s", command)
if command in device_details['IRcodes']:
log_debug("Device %s supports command %s", device_name, command)
# Only want to find one command e.g. PowerOn or PowerToggle
# We include the device name as we will need that when
# later figuring out what to turn on/off
output_cmd['SingleIRCommand']['single'] = construct_specific_IR_command(device_details, command, target, device_name, device_logname)
found = True
else:
log_debug("...doesn't support this capability")
return output_cmd
def StepIRCommands(device, capability, command_list):
cap_to_check = which_capability(capability)
device_name = device['friendly_name']
device_logname = device['log_name']
device_details = device['details']
target = device['target']
output_cmd = {}
if cap_to_check in device_details['supports']:
log_debug("Device %s supports the %s capability", device_name, capability)
output_cmd['StepIRCommands'] = {}
found = False
log_debug("StepIRCommands should check for key %s", command_list['key'])
output_cmd['StepIRCommands']['key'] = command_list['key']
for i in [ '+ve', '-ve' ]:
found = False
for command in command_list[i]:
if not found:
log_debug("Look for command %s", command)
if command in device_details['IRcodes']:
log_debug("Device %s supports command %s", device_name, command)
# Only want to find one command e.g. PowerOn or PowerToggle
# We include the device name as we will need that when
# later figuring out what to turn on/off
output_cmd['StepIRCommands'][i] = construct_specific_IR_command(device_details, command, target, device_name, device_logname)
found = True
else:
log_debug("...doesn't support this capability")
return output_cmd
def DigitsIRCommands(device, capability, command_list):
cap_to_check = which_capability(capability)
device_name = device['friendly_name']
device_logname = device['log_name']
device_details = device['details']
target = device['target']
output_cmd = {}
if cap_to_check in device_details['supports']:
log_debug("Device %s supports the %s capability", device_name, capability)
output_cmd['DigitsIRCommands'] = {}
if 'UseNameMap' in command_list:
map = command_list['UseNameMap']
log_debug("DigitsIRCommand for this directive can accept name map %s", map)
if map in device_details:
log_debug("Map present")
output_cmd['DigitsIRCommands']['NameMap'] = device_details[map].copy()
for i in [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]:
found = False
for command in command_list[i]:
if not found:
log_debug("Look for command %s", command)
if command in device_details['IRcodes']:
log_debug("Device %s supports command %s", device_name, command)
# Only want to find one command e.g. PowerOn or PowerToggle
# We include the device name as we will need that when
# later figuring out what to turn on/off
output_cmd['DigitsIRCommands'][i] = construct_specific_IR_command(device_details, command, target, device_name, device_logname)
found = True
else:
log_debug("...doesn't support this capability")
return output_cmd
def InputChoice(device, capability, command_list):
device_name = device['friendly_name']
device_logname = device['log_name']
device_details = device['details']
target = device['target']
output_cmd = {}
# Add commands to set all the devices in the chain to the correct input
# values.
if 'required_input' in device:
log_debug("Need to set %s to input %s", device_name, device['required_input'])
log_debug("device_details: %s", pp.pformat(device_details['IRcodes']))
output_cmd['SingleIRCommand'] = {}
output_cmd['SingleIRCommand']['single'] = construct_specific_IR_command(device_details, device['required_input'], target, device_name, device_logname)
return output_cmd
def Pause(device, capability, pause):
# This is an additional pause, typically to wait for kit to switch on
output_cmd = { 'Pause': pause }
return output_cmd
def construct_command_sequence(device_chain, capability, generic_commands):
# Construct the sequence of commands corresponding to a particular
# directive of a particular capability, for example "Play" for a
# "PlaybackController".
#
# The generic_commands is a dictionary of commands to be interpreted when a
# directive is received, each consisting of a primitive plus parameters as
# follows.
#
# SingleIRCommands - Send a single IR command. Primitive has a list of
# command names to search for in each device; use the
# first match found for each relevant device
#
# StepIRCommands - Directive is of form increase/decrease by N.
# Primitive is a dict with +ve and -ve command lists,
# interpreted as above.
#
# DigitsIRComamnds - Directive is a number to be converted to a sequence
# of IR commands for each decimal digit. Primitives
# is a dict with list of possible commands for each
# digit.
#
# InputChoice - Send IRCommands to set all the devices in the
# activity to the correct input setting. Typically
# used in "power on".
#
# Pause - Pause before sending anything further. Typically
# used to wait for kit to switch on. Primitive is
# length of pause in seconds.
#
# We map this to the specific sequence of commands for this users devices
# by substituting from the global database of devices.
#
# Note that we rely on dictionary ordering - not true for Python 2, true
# for Python 3.6 onwards.
#
# We do this by looping through all the devices in the activity, and for
# those which support this capability, looking for matches for the set of
# instructions.
commands = []
log_debug("Converting generic primitives %s to specific commands for capability %s for device chain %s", pp.pformat(generic_commands), capability, pp.pformat(device_chain))
for primitive in generic_commands:
log_debug("This primitive is %s", primitive)
for link in device_chain:
device = link['friendly_name']
device_logname = link['log_name']
device_details = link['details']
target = link['target']
log_debug("Check device %s", device)
commands.append(globals()[primitive](link, capability, generic_commands[primitive]))
log_debug("Commands for this directive:\n%s", pp.pformat(commands))
return commands