def post(self, request, device_id): """ Send data to device serial """ try: data = request.DATA['data'] except KeyError: return Response(status=status.HTTP_400_BAD_REQUEST) try: is_encoded = request.DATA['is_base64'] needs_encoding = not strtobool(is_encoded) except KeyError: needs_encoding = True except ValueError: return Response(status=status.HTTP_400_BAD_REQUEST) if needs_encoding: data = base64.b64encode(data) username, password, cloud_fqdn = get_credentials(request) if not username or not password or not cloud_fqdn: return Response(status=status.HTTP_400_BAD_REQUEST) conn = DeviceCloudConnector(username, password, cloud_fqdn) try: response = conn.send_serial_data(device_id, data) except HTTPError, e: return Response(status=e.response.status_code, data=e.response.text)
def put(self, request, device_id): io_command_pairs = [] io_set_setting_pairs = [] io_serial_data_values = [] # Sanitize and sort inputs for name, value in request.DATA.iteritems(): # May get '/' seperators, mixed case, etc. Strip out non-alphanum # chars, make uppercase. name = str(name).translate(None, self.delchars).upper() # Check for DIO and extract the bit position of this pin match = re.match(r"(DIO)(?P<bit>[0-9]+)", name) if match: bit = match.group('bit') # Convert boolean-ish values to True/False if type(value) == str or type(value) == unicode: try: value = bool(strtobool(value)) except ValueError: # Try to catch "high"/"low" if value.lower() == "high": value = True elif value.lower() == "low": value = False else: return Response(status=status.HTTP_400_BAD_REQUEST) io_command_pairs.append((int(bit), value)) # Else see if it looks like a traditional AT command elif len(name) == 2: # M0, etc AT command, used for PWM setting # Some commands require hex strings, others integers, others # arbitrary text...ug try: # Hex if name in ['M0', 'M1', 'IC', 'PR', 'PD', 'DS']: val_str = hex(int(value)) elif (name in ['LT', 'RP', 'IR', 'IF'] or name.startswith('T') or name.startswith('Q')): val_str = str(int(value)) else: # Use as is val_str = str(value) except ValueError: return Response(status=status.HTTP_400_BAD_REQUEST) io_set_setting_pairs.append((name, val_str)) # Handle serial output. Currently don't support sending to # different targets, so combine all # serial messages into a single payload elif name.startswith("SERIAL"): io_serial_data_values.append(value) else: # Unknown command provided return Response(status=status.HTTP_400_BAD_REQUEST) username, password, cloud_fqdn = get_credentials(request) if not username or not password or not cloud_fqdn: return Response(status=status.HTTP_400_BAD_REQUEST) conn = DeviceCloudConnector(username, password, cloud_fqdn) resp = {} try: # For IO command, need to generate two bitmasks - enable and level if len(io_command_pairs): enable_mask = 0 output_mask = 0 for bit, value in io_command_pairs: enable_mask |= 1 << int(bit) output_mask |= value << int(bit) resp = conn.set_output(device_id, hex(enable_mask), hex(output_mask)) if len(io_set_setting_pairs): # Because these settings belong to a single known group, we can # construct the request for the user new_settings = {'InputOutput': {}} for name, val in io_set_setting_pairs: new_settings['InputOutput'][name] = val resp = conn.set_device_settings(device_id, new_settings) if len(io_serial_data_values): data = "".join(io_serial_data_values) data = base64.b64encode(data) resp = conn.send_serial_data(device_id, data) except HTTPError, e: return Response(status=e.response.status_code, data=e.response.text)