Python: Object custom property glitch
The boolean flag is the simple part here. As you already assumed, those PropertyGroups are designed to hold Blender Properties only. So instead of

enabled = False


you should use

enabled = BoolProperty(default = False)  // which is anyways the default


The state property is more difficult. There are no Dictionary properties available to you, but maybe you can work around your issue by using a CollectionProperty instead?

Create a class first to hold your collection, for example:

class MyCollection(PropertyGroup):
    val1 = StringProperty()
    val2 = IntProperty(min = 0, max = 999)
    // etc etc


Then, in your Settings class, reference it like this:

variableCollection = CollectionProperty(type = MyCollection)


To add items to the collection, use this in your operator code:

x = context.object.my_settings.variableCollection.add()
x.val1 = 'This works'
x.val2 = 34


Alternatively, you can also nest PropertyGroups of course. That would be

nestedProperties = PointerProperty(type = MyCollection)


That would allow you to do:

context.object.my_settings.nestedProperties.val1 = 'This is nested'
context.object.my_settings.nestedProperties.val2 = 33


It depends on your situation in terms of what works best. But keep in mind that Blender's own property types are the only ones it can store with the file.

One last way to store Python data - but this does not save that data with the file - is simply using a key - value approach on the object. You can always use something like:

x = bpy.context.object
x['myCustomKey'] = myDesiredValue


The resulting data can then even be viewed in the viewport: