1# Copyright 2016 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import sys
16import time
17import hardware as hw
18import serial
19
20NUM_ROTATIONS = 10
21SLEEP_TIME = 2  # seconds
22
23DATA_DELIMITER = '\r\n'
24ROT_RIG_DEVICE = 'relay'
25ROT_RIG_VID = '04d8'
26ROT_RIG_PID = 'fc73'
27ROT_RIG_CHAN = '1'
28RELAY_BAUDRATE = 115200
29RELAY_COM_SLEEP = 0.05
30RELAY_SET_CMD = 'REL'
31VALID_RELAY_COMMANDS = ['ON', 'OFF']
32VALID_RELAY_CHANNELS = ['1', '2', '3', '4']
33SERIAL_SEND_TIMEOUT = 0.02
34
35
36def cmd_send(vid, pid, cmd_str):
37    """Wrapper for sending serial command.
38
39    Args:
40        vid:     str; vendor ID
41        pid:     str; product ID
42        cmd_str: str; value to send to device.
43    """
44    hw_list = hw.Device(ROT_RIG_DEVICE, vid, pid, '1', '0')
45    relay_port = hw_list.get_tty_path('relay')
46    relay_ser = serial.Serial(relay_port, RELAY_BAUDRATE,
47                              timeout=SERIAL_SEND_TIMEOUT,
48                              parity=serial.PARITY_EVEN,
49                              stopbits=serial.STOPBITS_ONE,
50                              bytesize=serial.EIGHTBITS)
51    try:
52        relay_ser.write(DATA_DELIMITER)
53        time.sleep(RELAY_COM_SLEEP)  # This is critcal for relay.
54        relay_ser.write(cmd_str)
55        relay_ser.close()
56    except ValueError:
57        print 'Port %s:%s is not open' % (vid, pid)
58        sys.exit()
59
60
61def set_relay_channel_state(vid, pid, channel, relay_state):
62    """Set relay channel and state.
63
64    Args:
65        vid:          str; vendor ID
66        pid:          str; product ID
67        channel:      str; channel number of relay to set. '1', '2', '3', or '4'
68        relay_state:  str; either 'ON' or 'OFF'
69    Returns:
70        None
71    """
72    if channel in VALID_RELAY_CHANNELS and relay_state in VALID_RELAY_COMMANDS:
73        cmd_send(vid, pid, RELAY_SET_CMD + channel + '.' + relay_state + '\r\n')
74    else:
75        print 'Invalid channel or command, no command sent.'
76
77
78def main():
79    """Main function.
80
81    expected rotator string is vid:pid:ch.
82    vid:pid can be found through lsusb on the host.
83    ch is hard wired and must be determined from the box.
84    """
85    for s in sys.argv[1:]:
86        if s[:8] == 'rotator=':
87            if len(s) > 8:
88                rotator_ids = s[8:].split(':')
89                if len(rotator_ids) == 3:
90                    vid = '0x' + rotator_ids[0]
91                    pid = '0x' + rotator_ids[1]
92                    ch = rotator_ids[2]
93                elif len(rotator_ids) == 1:
94                    if rotator_ids[0] in VALID_RELAY_CHANNELS:
95                        print ('Using default values %s:%s for VID:PID '
96                               'of rotator' % (ROT_RIG_VID, ROT_RIG_PID))
97                        vid = '0x' + ROT_RIG_VID
98                        pid = '0x' + ROT_RIG_PID
99                        ch = rotator_ids[0]
100                    elif rotator_ids[0] == 'default':
101                        print ('Using default values %s:%s:%s for VID:PID:CH '
102                               'of rotator' % (ROT_RIG_VID, ROT_RIG_PID,
103                                               ROT_RIG_CHAN))
104                        vid = '0x' + ROT_RIG_VID
105                        pid = '0x' + ROT_RIG_PID
106                        ch = ROT_RIG_CHAN
107                    else:
108                        print 'Invalid channel: %s' % rotator_ids[0]
109                        sys.exit()
110                else:
111                    err_string = 'Rotator ID (if entered) must be of form: '
112                    err_string += 'rotator=VID:PID:CH or rotator=CH'
113                    print err_string
114                    sys.exit()
115
116    print 'Rotating phone %dx' % NUM_ROTATIONS
117    for _ in xrange(NUM_ROTATIONS):
118        set_relay_channel_state(vid, pid, ch, 'ON')
119        time.sleep(SLEEP_TIME)
120        set_relay_channel_state(vid, pid, ch, 'OFF')
121        time.sleep(SLEEP_TIME)
122
123
124if __name__ == '__main__':
125    main()
126