I'm working on software to configure a device for communication over CANOpen. In CANOpen there's the concept of an Object Dictionary (OD) which is shared between the consumer and the producer. It acts as a contract between communication endpoints.
To customize what we want to visualize in our application we are building a configuration file in XML. One example is commands that can be executed on a device. An example can be that you need to move the arm of a robot up 500mm. I want to then be able to define this command as "Move Arm Z-Axis" and specify a parameter of a specific type with certain constraints (min, max, etc).
The approach I want to take is use a per device xml file where all these steps can be defined. It does however require me to write c# code inside the xml using specific parsing rules such as any code should be between "{{" "}}" brackets or use specific elements (e.g. <SetVariable>
).
<?xml version="1.0" encoding="UTF-8"?>
<DeviceConfiguration>
<Device name="CanOpenDevice1" />
<ParameterConfiguration>
<EntreesToExclude>
<EntryToExclude Index="0x206B" />
<EntryToExclude Index="0x2050" />
<EntryToExclude Index="0x20F1" />
<EntryToExclude Index="0x20F4" />
</EntreesToExclude>
<WriteToFlashCommand>
<WriteCommand Label="Write to Flash" Index="0x3000" SubIndex="0x0F" Value="0x000000FF" />
</WriteToFlashCommand>
</ParameterConfiguration>
<CommandConfiguration>
<Commands>
<WriteCommand Label="Connect Request ON" Index="0x20F2" Value="true" DataType="bool" />
<WriteCommand Label="Connect Request OFF" Index="0x20F2" Value="false" DataType="bool" />
<WriteCommand Label="Clear Faults" Index="0x2050" SubIndex="0x01" Value="0x66726c63" DataType="uint" />
<WriteCommand Label="Reboot" Index="0x2050" SubIndex="0x02" Value="0x00747372" DataType="uint" />
<!-- Executes in sequential order -->
<CommandInstructionSet Label="Sync RTC">
<SetVariable Name="now" Value="{{System.Datetime.UtcNow}}" />
<WriteCommand Index="0x206B" SubIndex="0x05" Value="{{$now.Second}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x06" Value="{{$now.Minute}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x07" Value="{{$now.Hour}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x08" Value="{{$now.Day}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x09" Value="{{$now.Month}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x0A" Value="{{$now.Year - 2000}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x0B" Value="{{System.DateTime.IsLeapYear($now.Year)}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x0C" Value="{{$now.DayOfWeek}}" DataType="ushort" />
<WriteCommand Index="0x206B" SubIndex="0x0E" Value="0x12345678" DataType="uint" />
</CommandInstructionSet>
<ReadCommand Label="Reboot" Index="0x2050" SubIndex="0x02" DataType="uint" />
</Commands>
</CommandConfiguration>
</DeviceConfiguration>
The idea is to use the Roslyn scripting api to execute and evaluate the code after parsing the syntax.
I would like to know your thoughts and if you know of a better approach to this case. One thing I have a problem with is that I have limited ways of preventing malicious code from sneaking in. The code however only runs on the local machine, not in the cloud or on another server so you'll only be messing up your own device.