Exemple #1
0
def send_hex(frequency, baud, repeat, data):
    """
        Send a hex string as hex over an RFcat radio

        :param frequency:
        :param baud:
        :param repeat:
        :param data:
        :return:
    """

    click.secho('Building RF Data from hex string: {}'.format(data), bold=True)
    rf_data = bitstring.BitArray(hex=data)

    # Print some information about what we have so far
    click.secho('Full PWM key:          {}'.format(rf_data.bin), fg='green')
    click.secho('RF data packet length: {}'.format(len(rf_data)), fg='green')
    click.secho('Packet as hex:         {}'.format(rf_data), fg='green')
    click.secho('Preparing radio', fg='yellow')

    # Setup the Radio
    d = rflib.RfCat()
    configure_dongle(d, frequency=frequency, pktflen=len(rf_data), baud=baud)

    # Transmit the data
    click.secho('Sending transmission \'{}\' time(s)...'.format(repeat),
                fg='red',
                bold=True)
    d.RFxmit(data=rf_data.tobytes(), repeat=repeat)

    # Idle the radio
    click.secho('Idling radio', fg='yellow')
    d.setModeIDLE()

    return
Exemple #2
0
def jam(frequency, data, baud, maxpower):
    """
        Jam a frequency by continuously sending crap.

        :param frequency:
        :param data:
        :param baud:
        :param maxpower:
        :return:
    """

    click.secho('Configuring Radio', fg='yellow')
    d = rflib.RfCat()
    configure_dongle(d,
                     frequency=frequency,
                     pktflen=len(data),
                     baud=baud,
                     maxpower=maxpower)

    click.secho('Starting jam on frequency: {}. Press [ENTER] to stop.'.format(
        frequency),
                fg='green')

    # Fire Ze Lazers!
    while not keystop():
        d.RFxmit(data=data)

    # Idle the radio
    click.secho('Idling radio', fg='yellow')
    d.setModeIDLE()
Exemple #3
0
 def radio(self):
     if self._radio is None:
         # Single radio configuration. The USB interface gets confused if this used multiple times.
         self._radio = rflib.RfCat()
         self._radio.setFreq(314973000)
         self._radio.setMdmModulation(rflib.MOD_ASK_OOK)
         self._radio.setMdmDRate(2400)
     return self._radio
Exemple #4
0
def send_binary(frequency, prefix, suffix, baud, repeat, data, full):
    """
        Send a binary string as hex over an RFcat radio

        :param frequency:
        :param prefix:
        :param suffix:
        :param baud:
        :param repeat:
        :param data:
        :param full:
        :return:
    """

    click.secho('Building RF Data from binary string: {}'.format(data),
                bold=True)

    if full:
        # Warn that the data length is a little short for a 'full' key
        if len(data) <= 12:
            click.secho('WARNING: Data specified as full binary '
                        'but its only {} long'.format(len(data)),
                        fg='yellow')

        # Convert the data to bytes for the radio to send
        rf_data = bitstring.BitArray(bin=data).tobytes()

    else:
        # Calculate the PWM version of the binary we got.
        rf_data_string = pwm_encode(data, suffix=suffix, prefix=prefix)
        click.secho('Full PWM key:          {}'.format(rf_data_string),
                    fg='green')

        # Convert the data to bytes for the radio to send
        rf_data = bitstring.BitArray(bin=rf_data_string).tobytes()

    # Print some information about what we have so far
    click.secho('RF data packet length: {}'.format(len(rf_data)), fg='green')
    click.secho('Packet as hex:         {}'.format(rf_data.encode('hex')),
                fg='green')
    click.secho('Preparing radio', fg='yellow')

    # Setup the Radio
    click.secho('Configuring Radio', fg='yellow')
    d = rflib.RfCat()
    configure_dongle(d, frequency=frequency, pktflen=len(rf_data), baud=baud)

    # Transmit the data
    click.secho('Sending transmission \'{}\' time(s)...'.format(repeat),
                fg='red',
                bold=True)
    d.RFxmit(data=rf_data, repeat=repeat)

    # Idle the radio
    click.secho('Idling radio', fg='yellow')
    d.setModeIDLE()

    return
Exemple #5
0
def main(argv):
    level = 1
    rxid = ''
    sysid = ''
    input_hex = ''
    output_hex = ''
    output_bin = ''
    try:
        opts, args = getopt.getopt(argv, "hl:r:s:",
                                   ["level=", "receiver=", "systemid"])
    except getopt.GetoptError as error:
        print(error)
        print(help_msg)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(help_msg)
            sys.exit()
        elif opt in ("-l", "--level"):
            level = int(arg)
        elif opt in ("-r", "--receiver"):
            rxid = int(arg)
        elif opt in ("-s", "--systemid"):
            sysid = int(arg)
    if len(sys.argv) == 1:
        print('Invalid input, program accepts the following input format:\n' +
              help_msg)
        sys.exit(2)

    level, rxid, sysid = ValidateInputs(level, rxid, sysid)
    #Generate packet hex
    input_hex = PacketValues(level, rxid, sysid)

    #Convert hex to binary ascii stream
    input_bin = hex_to_binary(input_hex)

    #Convert binary data to format that the radio is expecting. 1 = 1110 0 = 1000
    for bit in input_bin:
        if bit == '0':
            output_bin += '1000'
        elif bit == '1':
            output_bin += '1110'
        else:
            print("lolwut?")

    rf_data = bitstring.BitArray(bin=output_bin + data_spoiler).tobytes()
    keyLen = len(rf_data)
    #Configure Radio here.
    d = rflib.RfCat()
    ConfigureD(d)
    #Transmit here.
    print('Sending packet payload 4*: ' + input_hex)
    d.RFxmit(rf_data, repeat=3)
    d.setModeIDLE()
    print('Done!')
    quit()
def init():
    d = rflib.RfCat()

    # Set Modulation. We using On-Off Keying here
    d.setMdmModulation(rflib.MOD_ASK_OOK)

    # Configure the radio
    #d.makePktFLEN(len(rf_data)) # Set the RFData packet length
    d.setMdmDRate(4800)  # Set the Baud Rate
    d.setMdmSyncMode(0)  # Disable preamble
    d.setFreq(433920000)  # Set the frequency

    return d
Exemple #7
0
 def _open_data(self, data):
     if type(data) == str:
         if data == '-':
             data = rflib.RfCat()
             data._debug = 1
             freq = int(self._low_freq)
             spc = int(self._spacing)
             numChans = int((self._high_freq-self._low_freq) / self._spacing)
             data._doSpecAn(freq, spc, numChans)
         else:
             data = pickle.load(file(data,'rb'))
     if data is None:
         raise Exception('Data not found')
     return data
Exemple #8
0
def play(source, repeat):
    """
        Replay frames from a previous recording

        :param source:
        :param repeat:
        :return:
    """

    click.secho('Source Information:')
    click.secho('Recording Date:        {}'.format(
        datetime.fromtimestamp(source['date'])),
                bold=True,
                fg='green')
    click.secho('Recording Frequency:   {}'.format(source['frequency']),
                bold=True,
                fg='green')
    click.secho('Recording Baud:        {}'.format(source['baud']),
                bold=True,
                fg='green')
    click.secho('Recording Framecount:  {}'.format(source['framecount']),
                bold=True,
                fg='green')

    # Setup RFCat
    click.secho('Configuring Radio', fg='yellow')
    d = rflib.RfCat()
    configure_dongle(d,
                     frequency=source['frequency'],
                     pktflen=0,
                     baud=source['baud'])

    # Transmit the frames from the recordin
    click.secho('Processing {} frames from the source file'.format(
        source['framecount']),
                bold=True)
    for (index, ), frame in numpy.ndenumerate(source['frames']):
        oneline_print('Progress [{}/{}]'.format(index + 1,
                                                source['framecount']))

        # Transmit the frame!
        d.RFxmit(data=frame.decode('hex'), repeat=repeat)

    # Try and be nice to the radio by setting it to Idle.
    click.secho('\nIdling Radio\n', fg='yellow')
    d.setModeIDLE()

    return
Exemple #9
0
def configure_RfCat(rf_debug=False):
    """
	create Rflib obj
	Configure RfCat device
	returns Rflib obj
    """

    # Start up RfCat
    c = rflib.RfCat(debug=rf_debug)
    c.RESET()

    # Set Modulation. We using On-Off Keying here
    c.setMdmModulation(rflib.MOD_ASK_OOK)

    # Configure the radio
    c.makePktFLEN(230)  # Set the RFData packet length
    c.setMdmDRate(DRATE)  # Set the Baud Rate
    c.setMdmSyncMode(0)  # Disable preamble
    c.setMdmSyncWord(0x000)
    c.setFreq(rf_freq)  # Set the frequency
    c.setEnableMdmManchester(0)

    # c.setMaxPower()
    if TX_Power:
        c.setPower(TX_Power)

    if chan_bw:
        c.setMdmChanBW(chan_bw)

    if verbose:
        bw = c.getMdmChanBW()
        dr = c.getMdmDRate()
        f1 = c.getFreq()
        print("DRate:", dr, bw)
        print("Freq:", f1[0])

    return c
Exemple #10
0
import rflib
from bottle import route, run, abort
import devices.rfdevices as rf

d = rflib.RfCat()


@route('/fireplace/<action>')
def control_fireplace(action):
    if action == 'on':
        rf.Fireplace().turnon(d)
    elif action == 'off':
        rf.Fireplace().turnoff(d)
    else:
        abort(404, "Not Found")
    return "ok"


@route('/bedroom-2-light/<action>')
def control_light(action):
    if action == 'on':
        rf.Bedroom2FanLight().turn_light_on(d)
    elif action == "off":
        rf.Bedroom2FanLight().turn_light_off(d)
    else:
        abort(404, "Not Found")
    return "ok"


@route('/bedroom-2-fan/<action>')
def control_fan(action):
def main(argv):
    data = 1
    rxid = ''
    sysid = ''
    sysid_lower = False
    sysid_upper = False
    sysid_range = False
    sysid_single = False
    record = False
    bruteforce = False
    input_hex = ''
    output_hex = ''
    
    try:
        opts, args = getopt.getopt(argv,"hl:u:s:b:r:",["lower=","upper=","systemid","bruteforce","record"])
    except getopt.GetoptError as error:
        print(error)
        print(help_msg)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(help_msg)
            sys.exit()
        elif opt in ("-l", "--lower"):
            sysid_lower = int(arg)
            sysid_single = False
            record = False
        elif opt in ("-u", "--upper"):
            sysid_upper = int(arg)
            sysid_single = False
            record = False
        elif opt in ("-s", "--systemid"):
            sysid = int(arg)
            sysid_range = False
            sysid_single = True
            record = False
        elif opt in ("-r", "--record"):
            running = int(arg)
            bruteforce = False
            sysid_single = False
            sysid_range = False
            record = True
        elif opt in ("-b", "--bruteforce"):
            bruteforce = True
            sysid_single = False
            sysid_range = False
            record = False
            sysid_lower = 1
            sysid_upper = 16383

    if len(sys.argv) == 1:
        print('Invalid input, program accepts the following input format:\n' + help_msg)
        sys.exit(2)

    if (sysid_lower or sysid_upper) and sysid:
        print('Invalid input, cannot accept range AND single System ID!')
    if (sysid_lower and sysid_upper) and not bruteforce:
        print('Generating System ID ' + str(sysid_lower) + ' through ' + str(sysid_upper))
        sysid_range = True
        sysid_single = False
    if not (sysid_lower and sysid_upper) and sysid:
        print('Sending single System ID ' + str(sysid))
        sysid_range = False
    if (sysid_lower and sysid_upper) and bruteforce:
        print('Generating System ID ' + str(sysid_lower) + ' through ' + str(sysid_upper))
        sysid_range = False
        sysid_single = False


    if sysid_single:
        sysid = ValidateInput_sysid_single(sysid)
        #Generate packet hex
        input_hex = PacketValues(sysid, 6)
        #Convert hex to binary ascii stream
        input_bin = hex_to_binary(input_hex)
        input_bin = input_bin[4:] #Removing extra null byte
        output_bin = FormatBitFrame_tx(input_bin)
        #print('Configuring RfCat...')
        d = rflib.RfCat()
        d.setModeIDLE()
        #print('Configuring Radio...')
        ConfigureD(d)
        sync_frame = "000001"
        data_frame = "001000000001001000" #value = 2
        null_tail  = "000000"
        TransmitData(output_bin, input_hex, d, sync_frame, data_frame, null_tail, 3)
        time.sleep(0.01)
        d.setModeIDLE()
        print('Done!')
        quit()

    if sysid_range:
        sysid_lower = ValidateInput_sysid_lower(sysid_lower, sysid_upper)
        sysid_upper = ValidateInput_sysid_upper(sysid_lower, sysid_upper)
        #print('Configuring RfCat...')
        d = rflib.RfCat()
        d.setModeIDLE()
        #print('Configuring Radio...')
        ConfigureD(d)
        sync_frame = "000001"
        data_frame = "001000000001001000" #value = 2
        null_tail  = "000000"
        for i in range(sysid_lower, sysid_upper+1, 1):
            #Generate packet hex
            input_hex = PacketValues(i, 6)
            #Convert hex to binary ascii stream
            input_bin = hex_to_binary(input_hex)
            input_bin = input_bin[4:] #Removing extra null byte
            output_bin = FormatBitFrame_tx(input_bin)
            TransmitData(output_bin, input_hex, d, sync_frame, data_frame, null_tail, 3)
            time.sleep(0.005)
        d.setModeIDLE()
        print('Done!')
        quit()

    if bruteforce:
        sysid_lower = ValidateInput_sysid_lower(sysid_lower, sysid_upper)
        sysid_upper = ValidateInput_sysid_upper(sysid_lower, sysid_upper)
        #print('Configuring RfCat...')
        d = rflib.RfCat()
        d.setModeIDLE()
        #print('Configuring Radio...')
        ConfigureD(d)
        sync_frame = "000001 000001 001000 000001 001000"
        data_frame = "001000 001000 001000 000001 001000" #value = 2
        null_tail  = "000000"
        rand_list = list(range(sysid_lower, sysid_upper+1, 1))
        random.shuffle(rand_list)
        for i in rand_list:
            #Generate packet hex
            input_hex = PacketValues(i, 6)
            #Convert hex to binary ascii stream
            input_bin = hex_to_binary(input_hex).lstrip("0")
            #print(input_bin + ' ' + str(len(input_bin)))
            input_bin = PadBytes(14, input_bin)
            #print(input_bin + ' ' + str(len(input_bin)))
            output_bin = FormatBitFrame_tx(input_bin)
            TransmitData(output_bin, input_hex, d, sync_frame, data_frame, null_tail, 3)
            time.sleep(0.005)
        d.setModeIDLE()
        print('Done!')
        quit()

    if record:
        rxlist = []
        now = datetime.datetime.now()
        logfile = 'linear_' + str(now.isoformat()).replace(':','_') + '.log'
        print('Saving packet data to ' + logfile)
        log = open(logfile, 'w')
        log.write('Linear Packet Log\n')
        #print('Configuring RfCat...')
        d = rflib.RfCat()
        #d.setModeIDLE()
        #print('Configuring Radio...')
        ConfigureD(d)
        while running > 0:
            running = running-1
            print(str(running) + ' Seconds remaining')
            for payload in Capture(d):
                if '1' in payload[:1] and (len(payload) == 136) and (len(payload) % 2 == 0):
                    binary = "00000"+payload+"000000000"
                    if len(binary) == 150:
                        log = open(logfile, 'a')
                        now = datetime.datetime.now()
                        Linear_packet = []
                        Linear_packet_raw = FormatBitFrame_rx(binary)
                        log.write('-'*25 + '\n' + str(now.isoformat()) + '\nLinear Packet: ' + Linear_packet_raw)
                        print('-'*25 + '\n' + str(now.isoformat()) + '\nLinear Packet: ' + Linear_packet_raw)
                        Linear_packet_systemid_rx = str(int(Linear_packet_raw[1:len(Linear_packet_raw)-3], 2))
                        log.write('\nSystem ID: ' + Linear_packet_systemid_rx)
                        print('System ID: ' + Linear_packet_systemid_rx)
                        Linear_packet_data = str(int(Linear_packet_raw[len(Linear_packet_raw)-3:], 2))
                        log.write('\nData: ' + Linear_packet_data + '\n')
                        print('Data: ' + Linear_packet_data + '\n')
                        log.close()
                        Linear_packet += binary, Linear_packet_raw, Linear_packet_systemid_rx, Linear_packet_data
                        rxlist += Linear_packet
                else:
                    continue
        #for pkt in rxlist:
        #    print(pkt)
        d.setModeIDLE()
        print('Done!')

    if not [sysid_range, sysid_single, record, bruteforce]:
        print('Incomplete parameters specified!')
        print(help_msg)
Exemple #12
0
 def _create_device():
     if Radio.device is None:
         Radio.device = rflib.RfCat()
Exemple #13
0
def bruteforce(frequency, baud, maxpower, start, end, repeat, prefix, suffix):
    """
        Brute force an OOK signal by sending permutations of
        a bitstring.

        :param frequency:
        :param baud:
        :param maxpower:
        :param start:
        :param end:
        :param repeat:
        :param prefix:
        :param suffix:
        :return:
    """

    start = bitstring.BitArray(bin=start)
    end = bitstring.BitArray(bin=end)

    click.secho('Start binary   : \'{}\' or \'{}\' as an integer'.format(
        start.bin, start.uint),
                fg='green')
    click.secho('End binary     : \'{}\' or \'{}\' as an integer'.format(
        end.bin, end.uint),
                fg='green')

    # Ensure that the start value is less than the end value
    if start.uint > end.uint:
        click.secho('Start position is larger than end position.', fg='red')
        return

    click.secho('Generating {} combinations...'.format(end.uint - start.uint),
                fg='green',
                bold=True)

    # Placeholder for all of the PWM permutations that
    # will be calculated.
    permutations = []

    # Set the current value to the start value as a starting
    # point for the brute force
    current_value = start.uint

    # Loop over the range and generate PWM encoded strings to
    # send along with the radio
    while current_value < end.uint:
        # Get a proper BitArray instance of the binary
        binary = bitstring.BitArray(bin=bin(current_value))

        # Get the PWM version of the binary string
        pwm_data = pwm_encode(binary.bin, prefix=prefix, suffix=suffix)

        # Add the permutation and append the current value
        permutations.append(pwm_data)
        current_value += 1

    click.secho('Configuring Radio', fg='yellow')
    d = rflib.RfCat()
    configure_dongle(d,
                     frequency=frequency,
                     pktflen=len(permutations[0]),
                     baud=baud,
                     maxpower=maxpower)

    click.secho(
        'Running brute force with a total of ({} combinations * {} repeats) {} RF transmits.'
        .format(len(permutations), repeat,
                len(permutations) * repeat),
        bold=True)

    # Small function used to format a label for the progressbar
    def show_current_data(data):
        return '[Current PWM string: {}]'.format(data)

    # Run the brute force
    with click.progressbar(permutations,
                           show_pos=True,
                           item_show_func=show_current_data) as combinations:

        for combination in combinations:
            # Generate the bytes needed for the RFXmit
            rf_data = bitstring.BitArray(bin=combination).tobytes()

            # Send the data using the radio
            d.RFxmit(data=rf_data, repeat=repeat)

    # Idle the radio
    click.secho('Idling radio', fg='yellow')
    d.setModeIDLE()
Exemple #14
0
def search(start_frequency, end_frequency, baud, increment, framecount):
    """
        Search for a signal

        :param start_frequency:
        :param end_frequency:
        :param baud:
        :param increment:
        :param framecount:
        :return:
    """

    click.secho('Starting on frequency: {}'.format(start_frequency),
                fg='green')
    click.secho('Ending on frequency:   {}'.format(end_frequency), fg='red')

    # Setup RFCat
    click.secho('Configuring Radio', fg='yellow')
    d = rflib.RfCat()
    configure_dongle(d,
                     frequency=start_frequency,
                     pktflen=0,
                     baud=baud,
                     lowball=True)

    # The frequency variable is used to track the current
    # frequency that we are scanning.
    frequency = start_frequency

    # The signals variable will hold all of the frequencies
    # and the valid data packets found for that frequency.
    signals = dict()

    click.secho('\nScanning frequency range. Press [ENTER] to stop.',
                fg='green',
                bold=True)

    # Lables for the values that will update during scanning
    click.secho('Frequency | Framecount | Found', dim=True)

    # While ENTER has not yet been pressed, iterate over
    # the frequencies as calculated for x abount of frame counts.
    # Each time valid data is detected, the data frame is added
    # to a dictionary using the frequency it was detected on as
    # the key.
    while not keystop():

        # Read packets 'framecount' amount of times
        for framecounter in xrange(0, framecount):

            # Status Update. Spacing is to match up with the previously
            # echoed 'lables'.
            oneline_print('{} | {}/{}        | {}'.format(
                frequency, framecounter, framecount, len(signals)))

            # This try/except is just to catch the UsbTimeout
            # that gets thrown if data has not been received in
            # the time specified in RFrecv.
            try:

                # Get a packet from the RFcat radio
                pkt, _ = d.RFrecv(timeout=1000)
                packet = pkt.encode('hex')

                # If we have a 'valid' packet, append it as a frame
                # to the frequency. A valid packet is defined as one
                # that has 38 0's in its hex representation.
                if valid_packet(packet=packet, constraint='0' * 38):

                    # If this is the first time we are seeing valid
                    # data on this frequency, prepare a data dict
                    # with the first packet added.
                    if frequency not in signals:
                        signals[frequency] = {'data': [(pkt, packet)]}

                    # Otherwise, just append the packet we just got
                    # to the existing dict for this frequency
                    else:
                        signals[frequency]['data'].append((pkt, packet))

            # A timeout in RFrecv will raise an exception.
            except rflib.ChipconUsbTimeoutException:
                pass

        # Set the new frequency incremented by the
        # increment count. If we have passed the end
        # frequency, reset back to the start.
        if frequency > end_frequency:
            frequency = start_frequency
        else:
            frequency += increment

        # Update the radio to the new frequency
        d.setFreq(freq=frequency)

    # Try and be nice to the radio by setting it to Idle.
    click.secho('\nIdling Radio\n', fg='yellow')
    d.setModeIDLE()

    # If we found nothing, just end.
    if not signals:
        click.secho('No signals were found.', fg='red')
        return

    # Sort the output signals.
    # signals.items() translates into a list of tuples with
    # t[0] being the frequency and t[1] the data:
    #   eg:
    #       [(433800000, {'data': ['x', 'x', 'x']})]
    f = sorted(signals.items(),
               key=lambda t: (len(t[1]['data']), t[0]),
               reverse=True)

    # Iterate the sorted list, printing how many data packets
    # were found on what frequency.
    click.secho('# of valid packets per frequency', fg='green')
    click.secho('Frequency  |   # packets', bold=True)
    for frequency, data in f:
        click.secho('{}  |   {}'.format(frequency, len(data['data'])))

    return
Exemple #15
0
def record(frequency, baud, framecount, destination):
    """
        Record symbols from an RFCat dongle to a file.

        :param frequency:
        :param baud:
        :param framecount:
        :param destination:
        :return:
    """

    click.secho('Recording on frequency: {} to {}'.format(
        frequency, destination),
                fg='green')

    # Setup RFCat
    click.secho('Configuring Radio', fg='yellow')
    d = rflib.RfCat()
    configure_dongle(d,
                     frequency=frequency,
                     pktflen=0,
                     baud=baud,
                     lowball=True)

    # The final payload that will be written
    payload = {
        'date': time.mktime(datetime.now().timetuple()),
        'frequency': frequency,
        'baud': baud,
        'framecount': 0,
        'frames': []
    }

    # A help message to get maximum # of frames written to file.
    click.secho(
        'For maximum frames, press and release the remote multiple times.',
        fg='green')

    # Capture frames!
    for c in xrange(0, framecount):
        oneline_print('Progress [{}/{}] Frames: {}'.format(
            c, framecount, len(payload['frames'])))

        # This try/except is just to catch the UsbTimeout
        # that gets thrown if data has not been received in
        # the time specified in RFrecv.
        try:

            # Get a packet from the RFcat radio
            pkt, _ = d.RFrecv(timeout=1000)
            packet = pkt.encode('hex')

            # If we have a 'valid' packet, append it as a frame
            # to the frequency. A valid packet is defined as one
            # that has 38 0's in its hex representation.
            if valid_packet(packet=packet, constraint='0' * 38):
                payload['framecount'] += 1
                payload['frames'].append(packet)

        # A timeout in RFrecv will raise an exception.
        except rflib.ChipconUsbTimeoutException:
            pass

    # Try and be nice to the radio by setting it to Idle.
    click.secho('\nIdling Radio\n', fg='yellow')
    d.setModeIDLE()

    click.secho('Writing saved payload to: {}'.format(destination), bold=True)
    with open(destination, 'wb') as f:
        f.write(json.dumps(payload))

    return