Python CSV

Import Package

Download the indistinguishable-from-magic library, which contains the necessary magic module for interacting with hardware devices. Install it via your preferred package management system or add it to your project. Include the library in your script by creating a reference to it:

from indistinguishable_from_magic import magic as Magic

If you are planning to use a USB connection, ensure you install the appropriate USB driver for your system. For instance, you can use the Silicon Labs USB to UART driver and follow the installation wizard. This step is recommended during development.


Connecting to Hardware

To connect to a hardware device, initialize the connection with Magic.Device and specify the port. In this example, the hardware is connected via the COM7 port:

d = Magic.Device("COM7", False)
d.connect()

Ensure you specify the correct port name for your system:

  • Windows USB: COM# (e.g., COM7)

  • Mac USB: cu.SLAB_USBtoUART

If using Bluetooth, pair the device via the operating system first. On connection, a directory named MAGIC will be created in the same directory as your script, if it does not already exist.


Writing Data to CSV

The script automatically creates a timestamped .csv file in the MAGIC directory to store data from the device. The filename follows the format MAGIC/YYYYMMDDTHHMMSS.csv. For example:

dir_path = Magic.os.path.dirname(Magic.os.path.realpath(__file__)) + "/MAGIC"
filename = "{}/{}.csv".format(dir_path, Magic.datetime.datetime.now(Magic.datetime.UTC).strftime("%Y%m%dT%H%M%S.%fZ"))

Data is continuously read from the device using the d.read() method, which returns a list of ports. Each port's data is written as a row in the CSV file, with columns dynamically updated as new keys appear.


Data Access

To access and log device data, the script uses a dictionary structure:

  • Time Elapsed: The script tracks time in seconds (time_secs) using d.time.

  • Port Data: Each port's data is processed and merged into the results.

The following loop continuously reads data and writes it to the CSV:

while True:
    ports = d.read()
    res = {"time_secs": d.time}
    for p in ports:
        if p != -1:
            res.update(p)
    writer.writerow(res)
    print(ports)

To stop data collection, use a Keyboard Interrupt (Ctrl + C), which will gracefully exit the script.


Disconnecting from Hardware

The script automatically disconnects the device when the program ends or is interrupted. However, you can explicitly disconnect using:

d.disconnect()

Always disconnect before reloading or exiting to prevent errors.


Full Example

from indistinguishable_from_magic import magic as Magic
import csv

if __name__ == "__main__":
    d = Magic.Device("COM7", False)
    d.connect()
    dir_path = Magic.os.path.dirname(
        Magic.os.path.realpath(__file__)) + "/MAGIC"
    if not Magic.os.path.exists(dir_path):
        Magic.os.mkdir(dir_path)
    filename = "{}/{}.csv".format(dir_path, Magic.datetime.datetime.now(
        Magic.datetime.UTC).strftime("%Y%m%dT%H%M%S.%fZ"))

    time_header = "time_secs"
    columns = [time_header]
    fieldnames = []
    with open(filename, 'w', newline='') as csvfile:
        while True:
            try:
                ports = d.read()
                # update columns
                res = {"{}".format(time_header): d.time}
                for p in ports:
                    if p != -1:
                        for k in list(p.keys()):
                            if k not in columns:
                                columns += [k]
                        res.update(p)
                if fieldnames == []:
                    fieldnames = columns
                    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                    writer.writeheader()

                writer.writerow(res)
                print(ports)
            except KeyboardInterrupt:
                exit()

Last updated