import asyncio
import functools
import json
import websockets
import signal
import sys
import socket

import ipc_test
import ipc_constants
import ipc_util

from websockets.exceptions import WebSocketException


# Pool of passtrough connections (IP address -> WebSocket connection)
wc_neighbour_pool = dict()

# Pool of client connections subscribed for data sync (WebSocket connection -> Data to be synced)
wc_client_pool = dict()


# Get IPv4 address with default route
def get_local_ipv4():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        sock.connect(('10.255.255.255', 1))
        ip_addr = sock.getsockname()[0]
    except (PermissionError, OSError, socket.error):
        ip_addr = '127.0.0.1'
    finally:
        sock.close()
    return ip_addr


async def ws_handler(websocket, path):
    print('Client at {} connected.'.format(websocket.remote_address[0]))

    try:
        async for message in websocket:
            try:
                # print('Received command before decode : ' + message)
                command_array = json.loads(message)
            except json.JSONDecodeError:
                await ws_try_send(websocket, 'JSON first decode error is not valid.')
                return

            for command in command_array:
                try:
                    cmd_id = command['command']
                    print('Received command', cmd_id)
                except TypeError:
                    await ws_try_send(websocket, ipc_test.create_response_error('unknown', 'JSON is not valid.', '0'))
                    break
                except KeyError:
                    await ws_try_send(websocket, ipc_test.create_response_error('unknown', 'Entry is not valid.', '0'))
                    continue

                if cmd_id == 'subscribe':
                    global wc_client_pool
                    subscribed_to_what = command.get('arg4', ipc_constants.DEFAULT_ARRAY_EMPTY)

                    # Attempt to decode string array as a format check
                    try:
                        subscribed_string = json.dumps(subscribed_to_what)
                    except json.JSONDecodeError:
                        await ws_try_send(websocket, 'Invalid subscription list.')
                        continue

                    wc_client_pool[websocket] = subscribed_string
                    print('Client at {} subscribed to: \'{}\'.'.format(websocket.remote_address[0], subscribed_string))
                    continue
                if cmd_id == 'unsubscribe':
                    wc_client_pool_remove(websocket)
                    continue

                # 'arg1' is always a device index:
                #   If not present, malformed or equals 0, command is meant for the local device.
                #   If it's integer greater than 0, command is passed via websocket to neighbouring device whose index
                #     in our neighbour list matches arg1.
                device_index = 0
                try:
                    device_index = int(command.get('arg1', ipc_constants.DEFAULT_INT))
                except ValueError:
                    pass  # Malformed entry, ignoring it and pretending as if it was 0

                if device_index > 0:  # If we should forward the command to another device
                    remote_ip_addr = ipc_test.get_ip_address_of_neighbour_device(device_index)
                    resp_message = ''
                    if remote_ip_addr != '<NONE>':
                        command['arg1'] = 0  # Make sure that the command runs locally when arrives on remote device
                        print('Forwarding \'{}\' to {}'.format(cmd_id, remote_ip_addr))
                        resp_message = await ws_passthrough(remote_ip_addr, command, 0)

                    if resp_message == '<ERROR>' or remote_ip_addr == '<NONE>':
                        resp_message = ipc_test.create_response_error(
                            command_id=cmd_id,
                            error_message='Nonexisting on unreachable device.',
                            timestamp=command.get('query_time', ipc_constants.DEFAULT_STRING))
                else:  # Run on this device
                    print('Executing \'{}\' locally.'.format(cmd_id))
                    resp_message = handle_command(command)

                await ws_try_send(websocket, resp_message)

    except WebSocketException as e:
        print('ws_handler:', e)
        wc_client_pool_remove(websocket)


async def ws_client_publish(ws_pool):
    while True:
        for ws in ws_pool:
            try:
                await ws.send(ipc_test.get_json_data(ws_pool[ws], ''))
            except KeyError:
                print('Could not find')
            except WebSocketException:
                wc_client_pool_remove(ws)
                break   # To restart the loop on changed set
        await asyncio.sleep(1)


async def ws_passthrough(remote_ip_addr: str, payload: dict, retry_count: int):
    global wc_neighbour_pool

    # If this fails after two retries, give up and remove WS connection from the pool (if present)
    if retry_count > 2:
        wc_neighbour_pool_remove(remote_ip_addr)
        return "<ERROR>"
    if retry_count > 0:
        print('Retrying:', retry_count)

    # If the connection towards remote IP address exists, reuse it.
    # Otherwise, create it and put in the pool.
    try:
        ws = wc_neighbour_pool.get(remote_ip_addr, None)
        if ws is None:
            print('Creating new WS connection towards', remote_ip_addr)
            ws = await websockets.connect('ws://' + remote_ip_addr + ':5678')
            wc_neighbour_pool[remote_ip_addr] = ws
        else:
            print('Reusing existing WS connection towards', remote_ip_addr)

        send_res = await ws_try_send(ws, json.dumps([payload]))
        if not send_res:
            raise WebSocketException()
        rawstr = await ws_try_recv(ws)
        return rawstr
    except (TypeError, json.JSONDecodeError):
        return "<ERROR>"
    except (ConnectionAbortedError, ConnectionResetError) as e:
        wc_neighbour_pool_remove(remote_ip_addr)
        return await ws_passthrough(remote_ip_addr, payload, ++retry_count)
    except (WebSocketException, ConnectionRefusedError) as e:
        wc_neighbour_pool_remove(remote_ip_addr)
        return "<ERROR>"


def wc_neighbour_pool_remove(remote_ip_addr):
    try:
        global wc_neighbour_pool
        del wc_neighbour_pool[remote_ip_addr]
    except KeyError:
        pass


def wc_client_pool_remove(ws):
    try:
        global wc_client_pool
        del wc_client_pool[ws]
        print('Client at {} unsubscribed.'.format(ws.remote_address[0]))
    except KeyError:
        KeyError


async def ws_try_send(ws, data):
    try:
        await ws.send(data)
        return True
    except (WebSocketException, ConnectionRefusedError, ConnectionAbortedError, ConnectionResetError) as e:
        print('ws_try_send:', e)
        return False


async def ws_try_recv(ws):
    try:
        return await ws.recv()
    except (WebSocketException, ConnectionRefusedError, ConnectionAbortedError, ConnectionResetError) as e:
        print('ws_try_recv:', e)
        return ''


def handle_command(data: dict) -> str:
    cmd = data['command']

    # One-argument commands:
    if cmd == 'protocol_test':
        return ipc_test.protocol_test(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'eth_dhcp':
        return ipc_test.eth_config(None, data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'start_readback':
        return ipc_test.readback_ctl(True, data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'stop_readback':
        return ipc_test.readback_ctl(False, data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_readback':
        return ipc_test.readback_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_session':
        return ipc_test.session_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_home_page_status':
        return ipc_test.data_home_page_status_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_audio_delay':
        return ipc_test.data_audio_delay_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_audio_gain':
        return ipc_test.data_audio_gain_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_audio_source':
        return ipc_test.data_audio_source_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_hotspot':
        return ipc_test.data_hotspot_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_cloud':
        return ipc_test.data_cloud_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_network':
        return ipc_test.data_network_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_data_about':
        return ipc_test.data_about_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_preset_list_names':
        return ipc_test.speaker_preset_list_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_preset_folder_names':
        return ipc_test.speaker_preset_folder_names_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_all_speaker_preset_list_names':
        return ipc_test.all_speaker_preset_list_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_all_speaker_preset_folder_names':
        return ipc_test.all_speaker_preset_folder_names_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_global_preset_folder_names':
        return ipc_test.global_preset_folder_names_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_neighbour_list':
        return ipc_test.get_neighbour_list(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'clear_neighbour_list':
        return ipc_test.clear_neighbour_list(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_12':
        return ipc_test.get_bridge_mode_12(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_34':
        return ipc_test.get_bridge_mode_34(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_56':
        return ipc_test.get_bridge_mode_56(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_78':
        return ipc_test.get_bridge_mode_78(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_910':
        return ipc_test.get_bridge_mode_910(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_1112':
        return ipc_test.get_bridge_mode_1112(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_1314':
        return ipc_test.get_bridge_mode_1314(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_bridge_mode_1516':
        return ipc_test.get_bridge_mode_1516(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_lan_config':
        return ipc_test.get_lan_config(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_apex_cloud':
        return ipc_test.get_apex_cloud(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_spotify_config':
        return ipc_test.get_spotify_config(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_airplay_config':
        return ipc_test.get_airplay_config(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_hotspot_config':
        return ipc_test.get_hotspot_config(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_about':
        return ipc_test.get_about(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_status':
        return ipc_test.get_status(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'oem_get_status':
        return ipc_test.oem_get_status(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'oem_remove_code':
        return ipc_test.oem_remove_code(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_front_lock':
        return ipc_test.front_lock_get(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'run_locate':
        return ipc_test.locate_run(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'reset_factory':
        return ipc_test.factory_reset(data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'reset_audio':
        return ipc_test.audio_reset(data.get('query_time', ipc_constants.DEFAULT_STRING))
    # Two-argument commands:
    elif cmd == 'set_session':
        return ipc_test.session_set(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'eth_static':
        return ipc_test.eth_config(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'software_update':
        return ipc_test.software_update(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'hotspot_enable':
        return ipc_test.hotspot_enable(
            ipc_util.convert_str_to_dbus_msg(data.get('arg2')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_hotspot_config':
        return ipc_test.set_hotspot_config(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'cloud_enable':
        return ipc_test.cloud_enable(
            ipc_util.convert_str_to_dbus_msg(data.get('arg2')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'global_preset_set':
        return ipc_test.global_preset_set(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_mute':
        return ipc_test.solo_mute_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_gain':
        return ipc_test.solo_gain_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_polarity':
        return ipc_test.solo_polarity_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_delay_enable':
        return ipc_test.solo_delay_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_delay_value':
        return ipc_test.solo_delay_value_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_xover_hp_enable':
        return ipc_test.solo_xover_hp_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_xover_hp_type':
        return ipc_test.solo_xover_hp_type_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_xover_hp_freq':
        return ipc_test.solo_xover_hp_freq_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_xover_lp_enable':
        return ipc_test.solo_xover_lp_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_xover_lp_type':
        return ipc_test.solo_xover_lp_type_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_xover_lp_freq':
        return ipc_test.solo_xover_lp_freq_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_lim_rms_thres':
        return ipc_test.solo_lim_rms_thres_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_lim_rms_attack':
        return ipc_test.solo_lim_rms_attack_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_lim_rms_release':
        return ipc_test.solo_lim_rms_release_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_lim_peak_thres':
        return ipc_test.solo_lim_peak_thres_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_lim_peak_release':
        return ipc_test.solo_lim_peak_release_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_channel_source_pri':
        return ipc_test.solo_channel_source_pri_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_channel_source_sec':
        return ipc_test.solo_channel_source_sec_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_channel_name':
        return ipc_test.solo_channel_name_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_mute':
        return ipc_test.group_mute_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_gain':
        return ipc_test.group_gain_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_polarity':
        return ipc_test.group_polarity_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_delay_enable':
        return ipc_test.group_delay_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_delay_value':
        return ipc_test.group_delay_value_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_name':
        return ipc_test.group_name_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_assign_channel_to_group':
        return ipc_test.assign_channel_to_group_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_preset_file':
        return ipc_test.speaker_preset_file_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_preset_file_names':
        return ipc_test.speaker_preset_file_names_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_all_speaker_preset_file':
        return ipc_test.all_speaker_preset_file_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_all_speaker_preset_file_names':
        return ipc_test.all_speaker_preset_file_names_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_global_preset_file':
        return ipc_test.global_preset_file_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_global_preset_file_names':
        return ipc_test.global_preset_file_names_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'delete_speaker_preset_file':
        return ipc_test.delete_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'create_speaker_preset_folder':
        return ipc_test.create_speaker_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'delete_speaker_preset_folder':
        return ipc_test.delete_speaker_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'delete_all_speaker_preset_file':
        return ipc_test.delete_all_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'create_all_speaker_preset_folder':
        return ipc_test.create_all_speaker_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'delete_all_speaker_preset_folder':
        return ipc_test.delete_all_speaker_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_all_speaker_preset_file':
        return ipc_test.set_all_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'delete_global_preset_file':
        return ipc_test.delete_global_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_global_preset_file':
        return ipc_test.set_global_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'create_global_preset_folder':
        return ipc_test.create_global_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'delete_global_preset_folder':
        return ipc_test.delete_global_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_gain':
        return ipc_test.speaker_gain_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_polarity':
        return ipc_test.speaker_polarity_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_delay_enable':
        return ipc_test.speaker_delay_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_delay_value':
        return ipc_test.speaker_delay_value_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_fir_table':
        return ipc_test.speaker_fir_table_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_xover_hp_enable':
        return ipc_test.speaker_xover_hp_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_xover_hp_type':
        return ipc_test.speaker_xover_hp_type_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_xover_hp_freq':
        return ipc_test.speaker_xover_hp_freq_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_xover_lp_enable':
        return ipc_test.speaker_xover_lp_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_xover_lp_type':
        return ipc_test.speaker_xover_lp_type_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_xover_lp_freq':
        return ipc_test.speaker_xover_lp_freq_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_lim_rms_thres':
        return ipc_test.speaker_lim_rms_thres_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_lim_rms_attack':
        return ipc_test.speaker_lim_rms_attack_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_lim_rms_release':
        return ipc_test.speaker_lim_rms_release_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_lim_peak_thres':
        return ipc_test.speaker_lim_peak_thres_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_lim_peak_release':
        return ipc_test.speaker_lim_peak_release_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_local_description':
        return ipc_test.set_local_description(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_12':
        return ipc_test.set_bridge_mode_12(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_34':
        return ipc_test.set_bridge_mode_34(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_56':
        return ipc_test.set_bridge_mode_56(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_78':
        return ipc_test.set_bridge_mode_78(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_910':
        return ipc_test.set_bridge_mode_910(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_1112':
        return ipc_test.set_bridge_mode_1112(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_1314':
        return ipc_test.set_bridge_mode_1314(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_bridge_mode_1516':
        return ipc_test.set_bridge_mode_1516(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_apex_cloud':
        return ipc_test.set_apex_cloud(
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_spotify_config':
        return ipc_test.set_spotify_config(
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_airplay_config':
        return ipc_test.set_airplay_config(
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_freq_gen_frequency' :
        return ipc_test.settings_set_freq_gen_frequency(
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_freq_gen_gain' :
        return ipc_test.settings_set_freq_gen_gain(
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_pink_gen_gain' :
        return ipc_test.settings_set_pink_gen_gain(
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'oem_check_code' :
        return ipc_test.oem_check_code(
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_xover_hp_freq_from_preset' :
        return ipc_test.get_xover_hp_freq_from_preset(
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_xover_lp_freq_from_preset' :
        return ipc_test.get_xover_lp_freq_from_preset(
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_preset_files_from_folder' :
        return ipc_test.speaker_preset_files_from_folder_get(
            data.get('arg2',ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_all_speaker_preset_files_from_folder' :
        return ipc_test.all_speaker_preset_files_from_folder_get(
            data.get('arg2',ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_hiz_filter':
        return ipc_test.hiz_get_filter(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_amp_stage_disable':
        return ipc_test.amp_stage_disable_set(
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_front_lock':
        return ipc_test.front_lock_set(
            data.get('arg4', ipc_constants.DEFAULT_BOOL),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    # Three-argument commands:
    elif cmd == 'speaker_preset_set':
        return ipc_test.speaker_preset_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_peq_enable':
        return ipc_test.solo_peq_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_peq_type':
        return ipc_test.solo_peq_type_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_peq_freq':
        return ipc_test.solo_peq_freq_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_peq_gain':
        return ipc_test.solo_peq_gain_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_peq_q':
        return ipc_test.solo_peq_q_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_amp_module_disable':
        return ipc_test.amp_module_disable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_mute':
        return ipc_test.solo_mute_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_gain':
        return ipc_test.solo_gain_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_polarity':
        return ipc_test.solo_polarity_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_delay_enable':
        return ipc_test.solo_delay_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_delay_value':
        return ipc_test.solo_delay_value_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_xover_hp_enable':
        return ipc_test.solo_xover_hp_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_xover_hp_type':
        return ipc_test.solo_xover_hp_type_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_xover_hp_freq':
        return ipc_test.solo_xover_hp_freq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_xover_lp_enable':
        return ipc_test.solo_xover_lp_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_xover_lp_type':
        return ipc_test.solo_xover_lp_type_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_xover_lp_freq':
        return ipc_test.solo_xover_lp_freq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_lim_rms_thres':
        return ipc_test.solo_lim_rms_thres_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_lim_rms_attack':
        return ipc_test.solo_lim_rms_attack_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_lim_rms_release':
        return ipc_test.solo_lim_rms_release_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_lim_peak_thres':
        return ipc_test.solo_lim_peak_thres_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_lim_peak_release':
        return ipc_test.solo_lim_peak_release_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_channel_source_pri':
        return ipc_test.solo_channel_source_pri_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_channel_source_sec':
        return ipc_test.solo_channel_source_sec_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_channel_name':
        return ipc_test.solo_channel_name_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_peq_enable':
        return ipc_test.group_peq_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_peq_type':
        return ipc_test.group_peq_type_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_peq_freq':
        return ipc_test.group_peq_freq_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_peq_gain':
        return ipc_test.group_peq_gain_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_group_peq_q':
        return ipc_test.group_peq_q_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_mute':
        return ipc_test.group_mute_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_gain':
        return ipc_test.group_gain_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_polarity':
        return ipc_test.group_polarity_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_delay_enable':
        return ipc_test.group_delay_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_delay_value':
        return ipc_test.group_delay_value_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_name':
        return ipc_test.group_name_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'upload_speaker_preset_file':
        return ipc_test.upload_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4'),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'upload_all_speaker_preset_file':
        return ipc_test.upload_all_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4'),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_preset_file':
        return ipc_test.set_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'rename_speaker_preset_file':
        return ipc_test.rename_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'rename_speaker_preset_folder':
        return ipc_test.rename_speaker_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'rename_all_speaker_preset_file':
        return ipc_test.rename_all_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'rename_all_speaker_preset_folder':
        return ipc_test.rename_all_speaker_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'create_global_preset_file':
        return ipc_test.create_global_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'edit_global_preset_file':
        return ipc_test.edit_global_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'rename_global_preset_file':
        return ipc_test.rename_global_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'rename_global_preset_folder':
        return ipc_test.rename_global_preset_folder(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'upload_global_preset_file':
        return ipc_test.upload_global_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4'),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_peq_enable':
        return ipc_test.speaker_peq_enable_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_peq_type':
        return ipc_test.speaker_peq_type_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_peq_freq':
        return ipc_test.speaker_peq_freq_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_peq_gain':
        return ipc_test.speaker_peq_gain_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_peq_q':
        return ipc_test.speaker_peq_q_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_solo_channel_mixer_gain':
        return ipc_test.solo_channel_source_mixer_get(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_gain':
        return ipc_test.speaker_gain_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd =='set_speaker_mute':
        return ipc_test.speaker_mute_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_polarity':
        return ipc_test.speaker_polarity_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_delay_enable':
        return ipc_test.speaker_delay_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_delay_value':
        return ipc_test.speaker_delay_value_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_fir_table':
        return ipc_test.speaker_fir_table_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_ARRAY_EMPTY),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_hp_enable':
        return ipc_test.speaker_xover_hp_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_hp_type':
        return ipc_test.speaker_xover_hp_type_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_hp_freq':
        return ipc_test.speaker_xover_hp_freq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_lp_enable':
        return ipc_test.speaker_xover_lp_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_lp_type':
        return ipc_test.speaker_xover_lp_type_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_lp_freq':
        return ipc_test.speaker_xover_lp_freq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_lim_rms_thres':
        return ipc_test.speaker_lim_rms_thres_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_lim_rms_attack':
        return ipc_test.speaker_lim_rms_attack_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_lim_rms_release':
        return ipc_test.speaker_lim_rms_release_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_lim_peak_thres':
        return ipc_test.speaker_lim_peak_thres_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_lim_peak_release':
        return ipc_test.speaker_lim_peak_release_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'oem_set_code':
        return ipc_test.oem_set_code(
            data.get('arg3', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_hp_overide':
        return ipc_test.speaker_xover_hp_overide_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_BOOL),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_xover_lp_overide':
        return ipc_test.speaker_xover_lp_overide_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_BOOL),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'create_all_speaker_preset_file':
        return ipc_test.create_all_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))    
    elif cmd == 'edit_all_speaker_preset_file':
        return ipc_test.edit_all_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_speaker_preset_files_from_folder' :
        return ipc_test.speaker_preset_files_from_folder_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_preset_files_from_folder' :
        return ipc_test.speaker_preset_files_from_folder_set(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'get_all_speaker_preset_files_from_folder' :
        return ipc_test.all_speaker_preset_files_from_folder_get(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_all_speaker_preset_files_from_folder' :
        return ipc_test.all_speaker_preset_files_from_folder_set(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_hiz_filter':
        return ipc_test.hiz_set_filter(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_BOOL),
            data.get('query_time', ipc_constants.DEFAULT_STRING))

    # Four-argument commands:
    elif cmd == 'set_solo_peq_enable':
        return ipc_test.solo_peq_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_peq_type':
        return ipc_test.solo_peq_type_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_peq_freq':
        return ipc_test.solo_peq_freq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_peq_gain':
        return ipc_test.solo_peq_gain_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_peq_q':
        return ipc_test.solo_peq_q_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_peq_enable':
        return ipc_test.group_peq_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_peq_type':
        return ipc_test.group_peq_type_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_peq_freq':
        return ipc_test.group_peq_freq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_peq_gain':
        return ipc_test.group_peq_gain_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_peq_q':
        return ipc_test.group_peq_q_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_assign_channel_to_group':
        return ipc_test.assign_channel_to_group_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_peq_enable':
        return ipc_test.speaker_peq_enable_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            ipc_util.convert_str_to_dbus_msg(data.get('arg4')),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_peq_type':
        return ipc_test.speaker_peq_type_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_INT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_peq_freq':
        return ipc_test.speaker_peq_freq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_peq_gain':
        return ipc_test.speaker_peq_gain_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_speaker_peq_q':
        return ipc_test.speaker_peq_q_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_channel_mixer_gain':
        return ipc_test.solo_channel_source_mixer_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_FLOAT),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'create_speaker_preset_file':
        return ipc_test.create_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))    
    elif cmd == 'edit_speaker_preset_file':
        return ipc_test.edit_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_label_speaker_preset_file':
        return ipc_test.set_label_speaker_preset_file(
            data.get('arg2', ipc_constants.DEFAULT_STRING),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_BOOL),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_solo_peq':
        return ipc_test.solo_peq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_PEQ),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_group_peq':
        return ipc_test.group_peq_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_INT),
            data.get('arg4', ipc_constants.DEFAULT_PEQ),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_copy_channel_parameters':
        return ipc_test.copy_channel_parameters_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    elif cmd == 'set_copy_speaker_parameters':
        return ipc_test.copy_speaker_parameters_set(
            data.get('arg2', ipc_constants.DEFAULT_INT),
            data.get('arg3', ipc_constants.DEFAULT_STRING),
            data.get('arg4', ipc_constants.DEFAULT_STRING),
            data.get('query_time', ipc_constants.DEFAULT_STRING))
    # Unsupported commands:
    else:
        return 'Command not recognized.'


async def udp_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_socket.bind(('', 12000))
    msg = str.encode("Hello Client!")
    while True:
        data, client_address = server_socket.recvfrom(1024)
        # handle_udp_request(data, client_address)

        server_socket.sendto(msg, client_address)
        await asyncio.sleep(1)


class EchoServerProtocol:
    def connection_made(self, transport):
        self.transport = transport

    def datagram_received(self, data, addr):
        message = data.decode()
        print('Received %r from %s' % (message, addr))
        ret = ipc_test.readback_get(123456)
        print('Send %r to %s' % (ret, addr))
        self.transport.sendto(bytes(ret, "utf-8"), addr)

def main(exe, args):
    if sys.version_info[0] < 3:
        sys.exit("Must run using Python 3 or newer.")

    # ip_addr = get_local_ipv4()
    # print(f"Binding to {ip_addr}:5678...")
    print(f"Binding to any:5678...")
    start_server = websockets.serve(ws_handler=ws_handler, host='', port=5678, max_size=45242880)
    
    loop = asyncio.get_event_loop()
    # Register signal handler for SIGINT (Ctrl+C) and SIGTERM ('kill' command).
    # Needs to be done via event loop method in order to be able to interact with event loop itself (e.g. to stop it).
    loop.add_signal_handler(signal.SIGINT, functools.partial(signal_handler, loop=loop))
    loop.add_signal_handler(signal.SIGTERM, functools.partial(signal_handler, loop=loop))

    global wc_client_pool
    loop.create_task(ws_client_publish(wc_client_pool))
    # loop.create_task(udp_server())

    # listen = loop.create_datagram_endpoint(
    # EchoServerProtocol, local_addr=('0.0.0.0', 12000))
    # transport, protocol = loop.run_until_complete(listen)

    loop.run_until_complete(start_server)
    loop.run_forever()


def signal_handler(loop):
    print("Cleaning up...")
    loop.stop()
    sys.exit(0)


if __name__ == '__main__':
    main(sys.argv[0], sys.argv[1:])
