[{"data":1,"prerenderedAt":529},["ShallowReactive",2],{"docs-nav-docs_en":3,"docs-page-\u002Fen\u002Fcustom-extensions\u002Fcustom-protocol":190,"docs-surround-\u002Fen\u002Fcustom-extensions\u002Fcustom-protocol":526},[4],{"title":5,"path":6,"stem":7,"children":8},"En","\u002Fen","en",[9,13,37,50,68,86,105,119,138,159,176],{"title":10,"path":6,"stem":11,"navTitle":12},"QInsight Documentation","en\u002Findex","Overview",{"title":14,"navTitle":15,"path":16,"stem":17,"children":18,"page":36},"Getting Started",null,"\u002Fen\u002Fgetting-started","en\u002F01.getting-started",[19,23,27,31],{"title":20,"path":21,"stem":22,"navTitle":20},"What is QENEX Suite","\u002Fen\u002Fgetting-started\u002Fwhat-is-qenex-suite","en\u002F01.getting-started\u002F1.what-is-qenex-suite",{"title":24,"path":25,"stem":26,"navTitle":24},"What is QInsight","\u002Fen\u002Fgetting-started\u002Fwhat-is-qinsight","en\u002F01.getting-started\u002F2.what-is-qinsight",{"title":28,"path":29,"stem":30,"navTitle":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F01.getting-started\u002F3.installation",{"title":32,"path":33,"stem":34,"navTitle":35},"The QInsight user interface","\u002Fen\u002Fgetting-started\u002Fthe-qinsight-interface","en\u002F01.getting-started\u002F4.the-qinsight-interface","User interface",false,{"title":38,"navTitle":15,"path":39,"stem":40,"children":41,"page":36},"First Project","\u002Fen\u002Ffirst-project","en\u002F02.first-project",[42,46],{"title":43,"path":44,"stem":45,"navTitle":43},"Create a project","\u002Fen\u002Ffirst-project\u002Fcreate-a-project","en\u002F02.first-project\u002F1.create-a-project",{"title":47,"path":48,"stem":49,"navTitle":47},"Project structure","\u002Fen\u002Ffirst-project\u002Fproject-structure","en\u002F02.first-project\u002F2.project-structure",{"title":51,"navTitle":15,"path":52,"stem":53,"children":54,"page":36},"Connecting a Device","\u002Fen\u002Fconnecting-a-device","en\u002F03.connecting-a-device",[55,59,63],{"title":56,"path":57,"stem":58,"navTitle":56},"Add a driver","\u002Fen\u002Fconnecting-a-device\u002Fadd-a-driver","en\u002F03.connecting-a-device\u002F1.add-a-driver",{"title":60,"path":61,"stem":62,"navTitle":60},"Add a protocol","\u002Fen\u002Fconnecting-a-device\u002Fadd-a-protocol","en\u002F03.connecting-a-device\u002F2.add-a-protocol",{"title":64,"path":65,"stem":66,"navTitle":67},"Link a driver and a protocol","\u002Fen\u002Fconnecting-a-device\u002Flink-driver-and-protocol","en\u002F03.connecting-a-device\u002F3.link-driver-and-protocol","Linking",{"title":69,"navTitle":15,"path":70,"stem":71,"children":72,"page":36},"Variables","\u002Fen\u002Fvariables","en\u002F04.variables",[73,77,82],{"title":74,"path":75,"stem":76,"navTitle":74},"What is a variable","\u002Fen\u002Fvariables\u002Fwhat-is-a-variable","en\u002F04.variables\u002F1.what-is-a-variable",{"title":78,"path":79,"stem":80,"navTitle":81},"Conversion and presentation","\u002Fen\u002Fvariables\u002Fconversion-and-presentation","en\u002F04.variables\u002F2.conversion-and-presentation","Conversion & presentation",{"title":83,"path":84,"stem":85,"navTitle":83},"Add a variable","\u002Fen\u002Fvariables\u002Fadd-a-variable","en\u002F04.variables\u002F3.add-a-variable",{"title":87,"navTitle":15,"path":88,"stem":89,"children":90,"page":36},"Visualization","\u002Fen\u002Fvisualization","en\u002F05.visualization",[91,96,100],{"title":92,"path":93,"stem":94,"navTitle":95},"Create a workspace","\u002Fen\u002Fvisualization\u002Fcreate-a-workspace","en\u002F05.visualization\u002F1.create-a-workspace","Workspace",{"title":97,"path":98,"stem":99,"navTitle":97},"Add a control","\u002Fen\u002Fvisualization\u002Fadd-a-control","en\u002F05.visualization\u002F2.add-a-control",{"title":101,"path":102,"stem":103,"navTitle":104},"Bind a control to a variable","\u002Fen\u002Fvisualization\u002Fbind-a-control","en\u002F05.visualization\u002F3.bind-a-control","Bind a control",{"title":106,"navTitle":15,"path":107,"stem":108,"children":109,"page":36},"Running and Monitoring","\u002Fen\u002Frunning","en\u002F06.running",[110,114],{"title":111,"path":112,"stem":113,"navTitle":111},"Start and stop","\u002Fen\u002Frunning\u002Fstart-and-stop","en\u002F06.running\u002F1.start-and-stop",{"title":115,"path":116,"stem":117,"navTitle":118},"Watching live data","\u002Fen\u002Frunning\u002Fwatching-live-data","en\u002F06.running\u002F2.watching-live-data","Live data",{"title":120,"navTitle":15,"path":121,"stem":122,"children":123,"page":36},"Logging and Replay","\u002Fen\u002Flogging-and-replay","en\u002F07.logging-and-replay",[124,128,133],{"title":125,"path":126,"stem":127,"navTitle":125},"Logging data","\u002Fen\u002Flogging-and-replay\u002Flogging-data","en\u002F07.logging-and-replay\u002F1.logging-data",{"title":129,"path":130,"stem":131,"navTitle":132},"Replaying a log","\u002Fen\u002Flogging-and-replay\u002Freplaying-a-log","en\u002F07.logging-and-replay\u002F2.replaying-a-log","Replay",{"title":134,"path":135,"stem":136,"navTitle":137},"Exporting data","\u002Fen\u002Flogging-and-replay\u002Fexporting-data","en\u002F07.logging-and-replay\u002F3.exporting-data","Export",{"title":139,"navTitle":15,"path":140,"stem":141,"children":142,"page":36},"Python Scripts","\u002Fen\u002Fpython-scripts","en\u002F08.python-scripts",[143,147,151,155],{"title":144,"path":145,"stem":146,"navTitle":12},"Scripts overview","\u002Fen\u002Fpython-scripts\u002Fscripts-overview","en\u002F08.python-scripts\u002F1.scripts-overview",{"title":148,"path":149,"stem":150,"navTitle":148},"Accessing variables","\u002Fen\u002Fpython-scripts\u002Faccessing-variables","en\u002F08.python-scripts\u002F2.accessing-variables",{"title":152,"path":153,"stem":154,"navTitle":152},"Example script","\u002Fen\u002Fpython-scripts\u002Fexample-script","en\u002F08.python-scripts\u002F3.example-script",{"title":156,"path":157,"stem":158,"navTitle":156},"CSV post-processing","\u002Fen\u002Fpython-scripts\u002Fcsv-post-processing","en\u002F08.python-scripts\u002F4.csv-post-processing",{"title":160,"navTitle":15,"path":161,"stem":162,"children":163,"page":36},"Custom extensions","\u002Fen\u002Fcustom-extensions","en\u002F09.custom-extensions",[164,168,172],{"title":165,"path":166,"stem":167,"navTitle":165},"Custom driver","\u002Fen\u002Fcustom-extensions\u002Fcustom-driver","en\u002F09.custom-extensions\u002F1.custom-driver",{"title":169,"path":170,"stem":171,"navTitle":169},"Custom protocol","\u002Fen\u002Fcustom-extensions\u002Fcustom-protocol","en\u002F09.custom-extensions\u002F2.custom-protocol",{"title":173,"path":174,"stem":175,"navTitle":173},"Custom Control","\u002Fen\u002Fcustom-extensions\u002Fcustom-control","en\u002F09.custom-extensions\u002F3.custom-control",{"title":177,"navTitle":15,"path":178,"stem":179,"children":180,"page":36},"Reference","\u002Fen\u002Freference","en\u002F10.reference",[181,186],{"title":182,"path":183,"stem":184,"navTitle":185},"Drivers, protocols, and controls","\u002Fen\u002Freference\u002Fdrivers-protocols-controls","en\u002F10.reference\u002F1.drivers-protocols-controls","Drivers, protocols, controls",{"title":187,"path":188,"stem":189,"navTitle":187},"Troubleshooting","\u002Fen\u002Freference\u002Ftroubleshooting","en\u002F10.reference\u002F2.troubleshooting",{"id":191,"title":169,"body":192,"description":521,"extension":522,"meta":523,"navTitle":169,"navigation":320,"path":170,"seo":524,"stem":171,"__hash__":525},"docs_en\u002Fen\u002F09.custom-extensions\u002F2.custom-protocol.md",{"type":193,"value":194,"toc":515},"minimark",[195,199,233,238,459,463,486,490,500,504,511],[196,197,169],"h1",{"id":198},"custom-protocol",[200,201,202,203,210,211,214,215,221,222,225,226,229,230,232],"p",{},"A protocol is a plugin just like a driver (a DLL in the ",[204,205,206],"strong",{},[207,208,209],"code",{},"Protocols","\nfolder). It inherits from the generic ",[207,212,213],{},"ProtocolBase\u003CT>"," class, where ",[204,216,217,220],{},[207,218,219],{},"T","\nis the type of data the driver hands to the protocol"," — e.g. ",[207,223,224],{},"string"," for\ntext lines from the TCP driver or ",[207,227,228],{},"CanFrame"," for CAN frames. It is this ",[207,231,219],{},"\nthat makes a driver and a protocol fit together.",[234,235,237],"h2",{"id":236},"protocol-skeleton","Protocol skeleton",[239,240,245],"pre",{"className":241,"code":242,"language":243,"meta":244,"style":244},"language-csharp shiki shiki-themes github-light github-dark","public class MyProtocol : ProtocolBase\u003Cstring>\n{\n    public MyProtocol()   \u002F\u002F a parameterless constructor is mandatory\n    {\n        Specification = new SpecificationBase\n        {\n            Name = \"MyProtocol\",\n            Label = \"My Protocol\",\n            Version = \"1.0.0\",\n        };\n    }\n\n    public override void SetConfiguration() { \u002F* RawSettings *\u002F }\n\n    \u002F\u002F Create a protocol variable from commParams (\"key=value;...\")\n    public override IProtocolVariable CreateProtocolVariable(\n        IVariableBase variable, string commParams, bool isCommunicated)\n    {\n        var spec = MyVariableSpecification.Create(commParams);\n        return new MyProtocolVariable(variable, spec, isCommunicated);\n    }\n\n    \u002F\u002F Receive data from the driver and route it into variables\n    public override async Task AddReceivedDataToQueueAsync(\n        IEnumerable\u003Cstring> data, CancellationToken ct) { ... }\n\n    public override void ProcessReceivedData() { ... }\n\n    \u002F\u002F Encode variable values for sending to the device\n    public override IEnumerable\u003Cstring> Encode(\n        IEnumerable\u003CIProtocolVariable> variables) { ... }\n\n    public override Task StartAsync(CancellationToken ct) { ... }\n    public override Task StopAsync(CancellationToken ct) { ... }\n    public override void Dispose() { ... }\n}\n","csharp","",[207,246,247,255,261,267,273,279,285,291,297,303,309,315,322,328,333,339,345,351,356,362,368,373,378,384,390,396,401,407,412,418,424,430,435,441,447,453],{"__ignoreMap":244},[248,249,252],"span",{"class":250,"line":251},"line",1,[248,253,254],{},"public class MyProtocol : ProtocolBase\u003Cstring>\n",[248,256,258],{"class":250,"line":257},2,[248,259,260],{},"{\n",[248,262,264],{"class":250,"line":263},3,[248,265,266],{},"    public MyProtocol()   \u002F\u002F a parameterless constructor is mandatory\n",[248,268,270],{"class":250,"line":269},4,[248,271,272],{},"    {\n",[248,274,276],{"class":250,"line":275},5,[248,277,278],{},"        Specification = new SpecificationBase\n",[248,280,282],{"class":250,"line":281},6,[248,283,284],{},"        {\n",[248,286,288],{"class":250,"line":287},7,[248,289,290],{},"            Name = \"MyProtocol\",\n",[248,292,294],{"class":250,"line":293},8,[248,295,296],{},"            Label = \"My Protocol\",\n",[248,298,300],{"class":250,"line":299},9,[248,301,302],{},"            Version = \"1.0.0\",\n",[248,304,306],{"class":250,"line":305},10,[248,307,308],{},"        };\n",[248,310,312],{"class":250,"line":311},11,[248,313,314],{},"    }\n",[248,316,318],{"class":250,"line":317},12,[248,319,321],{"emptyLinePlaceholder":320},true,"\n",[248,323,325],{"class":250,"line":324},13,[248,326,327],{},"    public override void SetConfiguration() { \u002F* RawSettings *\u002F }\n",[248,329,331],{"class":250,"line":330},14,[248,332,321],{"emptyLinePlaceholder":320},[248,334,336],{"class":250,"line":335},15,[248,337,338],{},"    \u002F\u002F Create a protocol variable from commParams (\"key=value;...\")\n",[248,340,342],{"class":250,"line":341},16,[248,343,344],{},"    public override IProtocolVariable CreateProtocolVariable(\n",[248,346,348],{"class":250,"line":347},17,[248,349,350],{},"        IVariableBase variable, string commParams, bool isCommunicated)\n",[248,352,354],{"class":250,"line":353},18,[248,355,272],{},[248,357,359],{"class":250,"line":358},19,[248,360,361],{},"        var spec = MyVariableSpecification.Create(commParams);\n",[248,363,365],{"class":250,"line":364},20,[248,366,367],{},"        return new MyProtocolVariable(variable, spec, isCommunicated);\n",[248,369,371],{"class":250,"line":370},21,[248,372,314],{},[248,374,376],{"class":250,"line":375},22,[248,377,321],{"emptyLinePlaceholder":320},[248,379,381],{"class":250,"line":380},23,[248,382,383],{},"    \u002F\u002F Receive data from the driver and route it into variables\n",[248,385,387],{"class":250,"line":386},24,[248,388,389],{},"    public override async Task AddReceivedDataToQueueAsync(\n",[248,391,393],{"class":250,"line":392},25,[248,394,395],{},"        IEnumerable\u003Cstring> data, CancellationToken ct) { ... }\n",[248,397,399],{"class":250,"line":398},26,[248,400,321],{"emptyLinePlaceholder":320},[248,402,404],{"class":250,"line":403},27,[248,405,406],{},"    public override void ProcessReceivedData() { ... }\n",[248,408,410],{"class":250,"line":409},28,[248,411,321],{"emptyLinePlaceholder":320},[248,413,415],{"class":250,"line":414},29,[248,416,417],{},"    \u002F\u002F Encode variable values for sending to the device\n",[248,419,421],{"class":250,"line":420},30,[248,422,423],{},"    public override IEnumerable\u003Cstring> Encode(\n",[248,425,427],{"class":250,"line":426},31,[248,428,429],{},"        IEnumerable\u003CIProtocolVariable> variables) { ... }\n",[248,431,433],{"class":250,"line":432},32,[248,434,321],{"emptyLinePlaceholder":320},[248,436,438],{"class":250,"line":437},33,[248,439,440],{},"    public override Task StartAsync(CancellationToken ct) { ... }\n",[248,442,444],{"class":250,"line":443},34,[248,445,446],{},"    public override Task StopAsync(CancellationToken ct) { ... }\n",[248,448,450],{"class":250,"line":449},35,[248,451,452],{},"    public override void Dispose() { ... }\n",[248,454,456],{"class":250,"line":455},36,[248,457,458],{},"}\n",[234,460,462],{"id":461},"variable-specification","Variable specification",[200,464,465,466,469,470,473,474,477,478,481,482,485],{},"The addressing (\"which value belongs to which variable\") is defined by\na class derived from ",[207,467,468],{},"ProtVariableSpecification"," — e.g. the Raw CAN protocol\nkeeps ",[207,471,472],{},"CanId",", ",[207,475,476],{},"Offset",", and ",[207,479,480],{},"ByteOrder"," in it. The values come from the\n",[204,483,484],{},"Comm params"," text field the user fills in when assigning a variable.",[234,487,489],{"id":488},"deployment","Deployment",[200,491,492,493,495,496,499],{},"Copy the DLL into the ",[207,494,209],{}," folder. The protocol appears in the\n",[204,497,498],{},"Home → Project Configuration → Protocols"," list and is added to\na compatible driver.",[234,501,503],{"id":502},"next","Next",[200,505,506,510],{},[507,508,173],"a",{"href":509},"\u002Fcustom-extensions\u002Fcustom-control",".",[512,513,514],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":244,"searchDepth":263,"depth":263,"links":516},[517,518,519,520],{"id":236,"depth":257,"text":237},{"id":461,"depth":257,"text":462},{"id":488,"depth":257,"text":489},{"id":502,"depth":257,"text":503},"A custom protocol — ProtocolBase&lt;T&gt;, the variable specification, and deployment into the Protocols folder.","md",{},{"title":169,"description":521},"809JLOJXXKftlDYCpU6_3tgHyJLw4oAJ3dCu6odrb8Q",[527,528],{"title":165,"path":166,"stem":167,"navTitle":165,"children":-1},{"title":173,"path":174,"stem":175,"navTitle":173,"children":-1},1783626657072]