Registers a device model.

    Device model fields can only contain letters, numbers, and the following
    symbols: period (.), hyphen (-), underscore (_), space ( ) and plus (+).
    The first character of a field must be a letter or number.

def register_model(ctx, model, type, trait,
                   manufacturer, product_name, description):
    """Registers a device model.

    Device model fields can only contain letters, numbers, and the following
    symbols: period (.), hyphen (-), underscore (_), space ( ) and plus (+).
    The first character of a field must be a letter or number.
    """
    session, api_url, project_id = build_client_from_context(ctx)
    model_base_url = '/'.join([api_url, 'deviceModels'])
    model_url = '/'.join([model_base_url, model])
    payload = {
        'device_model_id': model,
        'project_id': project_id,
        'device_type': 'action.devices.types.' + type,
    }
    if trait:
        payload['traits'] = trait
    if manufacturer:
        payload.setdefault('manifest', {})['manufacturer'] = manufacturer
    if product_name:
        payload.setdefault('manifest', {})['productName'] = product_name
    if description:
        payload.setdefault('manifest', {})['deviceDescription'] = description
    logging.debug(json.dumps(payload))
    r = session.get(model_url)
    logging.debug(r.text)
    if r.status_code == 200:
        click.echo('Updating existing device model: %s' % model)
        r = session.put(model_url, data=json.dumps(payload))
    elif r.status_code in (400, 403, 404):
        click.echo('Creating new device model')
        r = session.post(model_base_url, data=json.dumps(payload))
    else:
        raise failed_request_exception('Failed to check existing device model',
                                       r)
    if r.status_code != 200:
        raise failed_request_exception('Failed to register model', r)
    click.echo('Model %s successfully registered' % model)