Is there a better design pattern for a SDK?
I see this as a good design. As for now I would change only those two things and consider changing one more:


CommandAdapter seems to be unnecessary separation of logic here. I would just move it as instance method of Command (CommandAdapter is being removed),
Since Device represents low-level communication with hardware via RS232 - seems like something unmanaged going there and in fact SerialPort is IDisposable so - Device should be either:

public class Device : IDisposable
{
    private ushort deviceId;
    private SerialPort devicePort;
    public Device(string comPort)
    {
        devicePort = new SerialPort(comPort, 115200);
        // ...
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            devicePort.Dispose();
        }
    }

    //...
}


so now we have clear IDisposable semantics:

using (var device = new Device("COM1"))
{
    // ...
}

I am not sure whether Command is used somewhere else, but currently it seems to be a class that is created just to call ToArray on it. It may be inefficent, it depends how many times it is called etc. So consider reducing Command and pass byte[] representing command directly:

public class Command
{
    internal static byte[] Format(ushort deviceId, byte commandId, params byte[] data)
    {
        //build byte array to match format needed
        return new byte[] { };
    }
}

public static class CommandFactory
{
    public static byte[] GetDeviceId()
    {
        return Command.Format(0, GET_DEVICE_CMD_ID);
    }

    public static byte[] DoFooBar(ushort deviceId, byte mode, byte option)
    {
        return Command.Format(deviceId, FOOBAR_CMD_ID, mode, option);
    }

    // ...
}

public class Device : IDisposable
{
    // ...

    public byte[] FooBar()
    {
        byte mode = 1;
        byte option = 0x52;
        byte[] cmd = CommandFactory.DoFooBar(deviceId, mode, option);
        return TransceiveCommand(cmd);
    }

    private byte[] TransceiveCommand(byte[] cmd)
    {
        devicePort.Write(cmd, 0, cmd.Length);
        byte[] response = DeviceResponseParser.GetResponse(devicePort);
        return response;
    }
}


In this case you can of course merge Command.Format into CommandFactory. This makes much less sophisticated design but if Command do not any additional value - maybe worth consideration.