CtrlJsonSerialization - Proposal of Ctrl Extension for JSON serialization and deserialization Gialousis Miltiadis Suder Mariusz BE-ICS-FD - CERN ...

Page created by Angel Davis
 
CONTINUE READING
CtrlJsonSerialization - Proposal of Ctrl Extension for JSON serialization and deserialization Gialousis Miltiadis Suder Mariusz BE-ICS-FD - CERN ...
CtrlJsonSerialization
                  Proposal of Ctrl Extension
           for JSON serialization and deserialization

Gialousis Miltiadis
Suder Mariusz
BE-ICS-FD

             26/05/2020              CtrlJsonSerialization   1
CtrlJsonSerialization - Proposal of Ctrl Extension for JSON serialization and deserialization Gialousis Miltiadis Suder Mariusz BE-ICS-FD - CERN ...
Motivation
        Have you ever …
                           Needed to store complex/compound data structures ?

 •     fwTrending needs to store vast configurations of trend pages that consist of trend areas, which
       in turn contain trend curves, with each of these having numerous properties that need to be
       editable.
 •     New AlarmScreen needs to store the configuration of filters, filtering widgets, layouts of the
       alarm table columns, etc.
 •     New UNICOS HMI needs to store "screen layouts" or "profiles", whereby users could save the
       content of each preview window with several properties, and then load/save/review modify
       them.

 •     Need to return a more complex data structure when the only available option is string or
       dyn_string (e.g. PanelOffReturn() which returns a dyn_float or dyn_string)

 Always a problem, but much more evident as we step into the consolidation of components like
 fwTrending, Alarmscreen as well as the integration of CTRL++.

                                   26/05/2020                                   CtrlJsonSerialization    2
Use Case: fwTrending
                                    Without serialization
Proposed object breakdown          •     DPT fwTrending_Trend
                                         •    dpe string title
                                         •    dpe dyn_string areas
                                   •     DPT fwTrending_TrendArea
                                         •    dpe string title
                                              …
                                         •    dpe string autoScroll
                                         •    dpe dyn_string curves
                                   •     DPT fwTrending_Curve
                                         •    dpe string title
                                              …
                                         •    dpe bool visible
                                   •     Custom API to dpSet/Get all those dps.

                                    JsonSerializer

                                   •     DPT fwTrending_Trend
                                         •    dpe string fwTrendingTrend
                                   •     string json = fwJsonSerialize (fwTrending_Trend)
                                   •     dpSet(sPlotDp + fwTrendingTrend, json);

                            26/05/2020                                                      CtrlJsonSerialization   3
Current approach - Shortcomings
• Every property is stored in a dedicated dp-element
• API that allows to manipulate the groups of settings lists each property as a separate
  argument in the system call

Even though in some cases this solution is sufficient and performant we can clearly see a lot of
issues with this approach

• Great difficulty in extending or altering the underlying saved properties. Ending up with
  overblow DP-Types, with huge number of elements that are rarely ever accessed, long API
  function signatures.
• Boilerplate repetition. Each different component developer is obliged to come up with a new
  small custom API.
• Inability to store Ctrl++ objects and more (vectors, shared_ptr etc) out of the box.

                                   26/05/2020                                CtrlJsonSerialization   4
JSON – Reaching solution
Having considered XML, we decided JSON was the way to go, providing encoding of data into a string.

• Well known standard, simple and with concise format
• Simplified structure of the DPT (reduced number of elements)
• Clean interface (ease of exchanging data with Ctrl extensions)
• Allows for future extensibility and compatibility without extra cost/overhead

Choosing Ctrl extension over native jsonEncode, jsonDecode functions.

• Limited support of nested structures (need for recursive encoding/decoding)
• Cannot work out of the box with custom Ctrl++ objects (need for extensive annotations).
• Overhead and difficulty of instantiating the proper data structures when decoding.

Decided to provide our own solution to overcome those limitations and have the possibility to extend it in
the future according to the needs of the JCOP community.

                                    26/05/2020                               CtrlJsonSerialization           5
API
string       fwJsonSerialize           (const type &obj|shared_ptr obj, [,
                                        mapping options = makeMapping()],
                                        bool compact = true)

int      fwJsonDeserialize (const string &json,
                             &obj|shared_ptr obj [,
                            mapping options = makeMapping()])

• Problems reported with exceptions, use try…catch statement
      try{
          fwJsonDeserialize("{\"a\":4,\"b\":true}", obj);
      }catch{
          DebugTN(getLastException());
      }

• Options mapping
  •   Already included in functions signatures, to be implemented later

                              26/05/2020                       CtrlJsonSerialization   6
Current State – Highlights
• Implemented support for serialization and deserialization of:
  • All built-in WinCC OA types used in JCOP framework
  • New CTRL++ types shared_ptr, vector and user defined types: classes/structs/enums
  • Nested objects of different types and at different depth

• Format of serialized data compatible with jsonEncode() output
  • Few exceptions for less common types

• Selection of output JSON format
  • Human readable or concise

                             26/05/2020                        CtrlJsonSerialization                7
Planned Features
• Implementation of options mapping for serialization and deserialization
  • Serialization                          • Deserialization
    • "depth" int                            • "depth" int
    • "noSerialize" dyn_string
    • "serializePtrTarget" bool

• Support for type annotation
  • shared_ptr of base class with object of derived class
  • anytype/mixed variable, array or mapping element

• Function for querying particular value/object stored in JSON document
  • int fwJsonPeek(const string &json, const string &query,
                    &obj|shared_ptr obj, mapping options = makeMapping())

                             26/05/2020                        CtrlJsonSerialization    8
Summary & Roadmap Proposal
If accepted by JCOP users community
• First 'preview' version ready to be included in the JCOP framework
  • Basic set of features provided – functionality of WinCC OA built-in functions + serialization of complex
    structures and deserialization to the output argument type
  • Covers use cases of storing/exchanging data structures of known type
  • For evaluation in development environment
  • API relatively stable, but it may be a subject to change if requested and approved at JCOP forum

• Further development
  • Implementing planned features
  • Users requests – we count on your feedback!

• Production-ready version to be delivered in autumn

                             26/05/2020                        CtrlJsonSerialization                           9
home.cern
Considered features
• Other options:
  • Deserialization
     • "stopAtFirstError" bool
     • "strictType" bool

• Possibility of declaring members excluded from serialization inside a class
static const dyn_string _no_serialize = makeDynString("member1", "member2", "member3",
"member4.nested1");

• Class methods for serialization and deserialization – if defined, used by
  fwJson[De]Serialize() instead of default behaviour
class Path{
       dyn_string path_elements;
       public string _serialize(){return strjoin(path_elements, "/");}
};

                             26/05/2020            CtrlJsonSerialization                 11
Remarks on storing serialized data

• For member of complex data structure, that needs to be accessed frequently (for
  example with dpQuery() or in a dpQueryConnect() callback) it is better not to serialize
  it, but rather store it in a separated DPE
  • Developer is responsible for proper design
  • Use case for noSerialize option

                            26/05/2020             CtrlJsonSerialization                    12
Quality assurance
• Automated unit tests in gitlab CI pipeline
  • Serialization and deserialization of different types (including nested ones)
  • Code coverage: ~75% (for now testing only happy path)

• Manually triggered unit tests, runned with tool to detect memory issues (valgrind)

• Performance tests to be prepared

                             26/05/2020                        CtrlJsonSerialization   13
Use Case: ScreenLayout
                                                  This is a simplified form of the UnHMI_ScreenLayout
                                                  data structure.

                                                  The properties of those classes can easily be
                                                  extended or modified at any time.

On the right, we can see the debug
output of an instance of the above class

Below we can see the same instance
serialized, in json string format, after
using our CTRL extension.

                                     26/05/2020                                  CtrlJsonSerialization   14
Use Case: Alarm Screen
                      Alarm Screen Configuration                   Grouping rows in the table                         Filter Configuration

                                                   {
{                                                      "GroupingConfiguration": {               {
    "ProxyModelConfiguration": {                         "columnWidth": 250,                        "filterRulesSets": [
     "AlarmModelConfiguration": {                        "groupHeader": "Group",                      {
       "AlarmSourceConfiguration": {                     "groupingRules": [                             "filters": [
         "fromTemplate": "",                               {                                              {
         "whereTemplate": "“                                 "alarmPropId": "application",                  "pattern": "*CAEN*",
       },                                                    "groupingRole": "display",                     "source": "this",
       "blockingTime": 2000,                                 "sortAscending": true,                         "valueId": "dpElement“
       "plugins": [        "AlarmPropJCOP"   ],              "textFormat": "“                             },
       "embeddedFilters": {                                },                                             {
              }                                            {                                                "pattern": "*My device description*",
     },                                                      "alarmPropId": "domain",                       "source": "this",
     "columns": [                                            "groupingRole": "display",                    "valueId": "deviceDescription“
       {                                                     "sortAscending": true,                       },
         "id": "Abbreviation",                               "textFormat": "“                             {
         "title": "Short Sign",                            },                                               "singleValue": {
         "backColor": {                                    {                                                "QString": "Local“
           "id": "AlertColor“                                "alarmPropId": "nature",                      },
         }                                                   "groupingRole": "display",                      "source": "this",
       },                                                    "sortAscending": true,                          "valueId": "scope“
       {                                                    "textFormat": "“                               }
         "id": "dpElement",                                }                                            ],
         "title": "Device DP Element“                    ]                                              "include": true
       },                                              }                                              },
       ….                                          }                                                  {
       ]                                                                                                "filters": [
     },                                                                                                   {
     "UserSettings": {                                                                                      "pattern": "*Other interesting devices*",
       "showFilterWidget": true,                                                                            "source": "this",
       "showFooterWidget": true,                                                                            "valueId": "deviceDescription“
       "showFilterView": "none",                                                                          },
       "filterSetDp": "_NgAsFilterSet000001",                                                             {
       "visibleColumns": [                                                                                  "pattern": "*With an interesting logical name*",
         {                                                                                                  "source": "this",
           "columnTitle": "Short Sign",                                                                     "valueId": "alias“
          "width": 90,                                                                                    }
           "visible": true    },                                                                        ],
          …                                                                                             "include": true
         {                                                                                            }
           "columnTitle": "Time",                                                                   ]
           "width": 177                                                                         }
         }
       ]
     },
     "Filter": {
       "filterName": "Default filter",
       "structureFilter": {

            },   "textFilter": "*“
        }
    }

                                                        26/05/2020                                                                CtrlJsonSerialization        15
Use Case: Alarm Screen
Filter Configuration for New Alarm Screen    Serialized vector
                                             [
                                                  {
                                                    "filters": [
                                                       {
                                                         "pattern": "*CAEN*",
                                                         "source": "this",
                                                         "valueId": "dpElement"
                                                       },
                                                       {
                                                         "pattern": "*My device description*",
                                                         "source": "this",
                                                         "valueId": "deviceDescription"
                                                       }
                                                    ],
                                                    "include": true
                                                  },
                                                  {
                                                    "filters": [
                                                       {
                                                         "pattern": "*Other interesting devices*",
                                                         "source": "this",
                                                         "valueId": "deviceDescription"
                                                       }
                                                    ],
                                                    "include": true
                                                  }
                                             ]

                         26/05/2020         CtrlJsonSerialization                                    16
You can also read