# 样品

以下示例通过 API 说明了 QSH 的端到端用例，使用户能够根据部署需求有效配置传感器。

## QSH 客户端 API 工作流

传感器应用客户端与低功耗处理器上可用的 QSH 进行交互。QSH 公开的 API 称为应用程序的 QSH 客户端 API。下图显示了 QSH 客户端 API 的详细细分和使用情况。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- 由 Microsoft Visio, SVG Export 生成 qsh-client-api-workflow.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.97917in" height="5.63542in" viewbox="0 0 358.5 405.75" xml:space="preserve" color-interpolation-filters="sRGB" class="st19"><v:documentproperties v:langid="2052">	<v:userdefs>		<v:ud v:nameu="msvNoAutoConnect" v:val="VT0(1):26"></v:ud>	</v:userdefs></v:documentproperties>
<style>.svg-1 .st1 { fill: #f7f8fa; stroke: none; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.75 }
.svg-1 .st2 { fill: #f7f8fa; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1 }
.svg-1 .st3 { fill: #000000; font-family: SimHei; font-size: 1.00001em }
.svg-1 .st4 { fill: #000000; font-family: Arial; font-size: 1.00001em }
.svg-1 .st5 { fill: none }
.svg-1 .st6 { stroke: #000000; stroke-dasharray: 7, 5; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1 }
.svg-1 .st7 { marker-end: url("#mrkr5-20"); stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1 }
.svg-1 .st8 { fill: #000000; fill-opacity: 1; stroke: #000000; stroke-opacity: 1; stroke-width: 0.28409102939153 }
.svg-1 .st9 { fill: #ffffff; stroke: none; stroke-linecap: butt; stroke-width: 7.2 }
.svg-1 .st10 { fill: #000000; font-family: Arial; font-size: 0.833336em }
.svg-1 .st11 { marker-start: url("#mrkr5-28"); stroke: #000000; stroke-dasharray: 7, 5; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1 }
.svg-1 .st12 { fill: #000000; font-family: SimHei; font-size: 0.833336em }
.svg-1 .st13 { font-family: Arial; font-size: 1em }
.svg-1 .st14 { fill: none; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1 }
.svg-1 .st15 { fill: none; stroke: none; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.75 }
.svg-1 .st16 { fill: #000000; font-family: Arial; font-size: 0.666664em }
.svg-1 .st17 { marker-end: url("#mrkr5-128"); stroke: #000000; stroke-linecap: butt; stroke-width: 0.999999 }
.svg-1 .st18 { fill: #000000; fill-opacity: 1; stroke: #000000; stroke-opacity: 1; stroke-width: 0.28409078197635 }
.svg-1 .st19 { fill: none; fill-rule: evenodd; font-size: 12px; overflow: visible; stroke-linecap: square; stroke-miterlimit: 3 }</style>
<defs id="Markers">	<g id="lend5">		<path d="M 2 1 L 0 0 L 1.98117 -0.993387 C 1.67173 -0.364515 1.67301 0.372641 1.98465 1.00043 " style="stroke:none"></path>	</g>	<marker id="mrkr5-20" class="st8" v:arrowtype="5" v:arrowsize="2" v:setback="6.16" refx="-6.1599973914988" orient="auto" markerunits="strokeWidth" overflow="visible">		<use xlink:href="#lend5" transform="scale(-3.5199985094279,-3.5199985094279) "></use>	</marker>	<marker id="mrkr5-28" class="st8" v:arrowtype="5" v:arrowsize="2" v:setback="0" refx="0" orient="auto" markerunits="strokeWidth" overflow="visible">		<use xlink:href="#lend5" transform="scale(3.5199985094279) "></use>	</marker>	<marker id="mrkr5-128" class="st18" v:arrowtype="5" v:arrowsize="2" v:setback="0" refx="-0" orient="auto" markerunits="strokeWidth" overflow="visible">		<use xlink:href="#lend5" transform="scale(-3.520001575001,-3.520001575001) "></use>	</marker></defs><g v:mid="0" v:index="1" v:groupcontext="foregroundPage">	<title>Page-1</title>	<v:pageproperties v:drawingscale="1" v:pagescale="1" v:drawingunits="19" v:shadowoffsetx="9.00001" v:shadowoffsety="-9.00001"></v:pageproperties>	<g id="shape1-1" v:mid="1" v:groupcontext="shape" transform="translate(18.375,-19.1248)">		<title>shape30-1</title>		<rect x="0" y="36.75" width="321.75" height="369" class="st1"></rect>	</g>	<g id="shape2-3" v:mid="2" v:groupcontext="shape" transform="translate(73.2501,-356.75)">		<title>shape2-3</title>		<desc>Application</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="42.75" cy="392.25" width="85.51" height="27"></v:textrect>		<rect x="0" y="378.75" width="85.5001" height="27" class="st2"></rect>		<text x="18.75" y="396.15" class="st3" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>应用程序</text>		</g>	<g id="shape3-6" v:mid="3" v:groupcontext="shape" transform="translate(202.625,-356.75)">		<title>shape4-6</title>		<desc>libSensingHubSession</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="66.375" cy="392.25" width="132.76" height="27"></v:textrect>		<rect x="0" y="378.75" width="132.75" height="27" class="st2"></rect>		<text x="6.34" y="395.85" class="st4" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>libSensingHubSession</text>		</g>	<g id="shape4-9" v:mid="4" v:groupcontext="shape" transform="translate(520.625,49) rotate(90)">		<title>shape5-9</title>		<path d="M0 405.75 L306.07 405.75 L0 405.75 Z" class="st5"></path>		<path d="M0 405.75 L306.07 405.75" class="st6"></path>	</g>	<g id="shape5-12" v:mid="5" v:groupcontext="shape" transform="translate(674.75,49) rotate(90)">		<title>shape6-12</title>		<path d="M0 405.75 L305.85 405.75 L0 405.75 Z" class="st5"></path>		<path d="M0 405.75 L305.85 405.75" class="st6"></path>	</g>	<g id="shape6-15" v:mid="6" v:groupcontext="shape" transform="translate(114.875,-338.75)">		<title>shape7-15</title>		<desc>getSession</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L147.96 405.75 L147.96 405.75" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="52.3234" y="399.75" width="49.4783" height="12.0001" class="st9"></rect>		<text x="52.32" y="408.75" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>getSession</text>		</g>	<g id="shape7-23" v:mid="7" v:groupcontext="shape" transform="translate(114.875,-320.75)">		<title>shape8-23</title>		<desc>ISession*</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L5.8 405.75 L6.16 405.75 L154.12 405.75" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="55.939" y="399.75" width="42.2468" height="12.0001" class="st9"></rect>		<text x="55.94" y="408.75" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>ISession*</text>		</g>	<g id="shape8-31" v:mid="8" v:groupcontext="shape" transform="translate(114.875,-302.75)">		<title>shape9-31</title>		<desc>Open</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L147.96 405.75 L147.96 405.75" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="64.8311" y="399.75" width="24.463" height="12.0001" class="st9"></rect>		<text x="64.83" y="408.75" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>Open</text>		</g>	<g id="shape9-38" v:mid="9" v:groupcontext="shape" transform="translate(114.875,-284.75)">		<title>shape10-38</title>		<desc>success/fail</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L5.8 405.75 L6.16 405.75 L154.12 405.75" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="55.6732" y="399.249" width="42.7786" height="13.0037" class="st9"></rect>		<text x="55.67" y="409" class="st12" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>成功<tspan class="st13">/</tspan>失败</text>		</g>	<g id="shape10-46" v:mid="10" v:groupcontext="shape" transform="translate(23.75,-131.75)">		<title>shape11-45</title>		<rect x="0" y="263.438" width="310.5" height="142.312" class="st14"></rect>	</g>	<g id="shape11-48" v:mid="11" v:groupcontext="shape" transform="translate(114.875,-253.25)">		<title>shape12-47</title>		<desc>setCallBacks</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L147.96 405.75 L147.96 405.75" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="48.1632" y="399.75" width="57.7988" height="12.0001" class="st9"></rect>		<text x="48.16" y="408.75" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>setCallBacks</text>		</g>	<g id="shape12-55" v:mid="12" v:groupcontext="shape" transform="translate(114.875,-237.5)">		<title>shape13-54</title>		<desc>success/fail</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L5.8 405.75 L6.16 405.75 L154.12 405.75" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="55.6732" y="399.249" width="42.7786" height="13.0037" class="st9"></rect>		<text x="55.67" y="409" class="st12" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>成功<tspan class="st13">/</tspan>失败</text>		</g>	<g id="shape13-63" v:mid="13" v:groupcontext="shape" transform="translate(114.875,-212.75)">		<title>shape14-61</title>		<desc>sendRequest</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L147.96 405.75 L147.96 405.75" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="47.5969" y="399.75" width="58.9312" height="12.0001" class="st9"></rect>		<text x="47.6" y="408.75" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>sendRequest</text>		</g>	<g id="shape14-70" v:mid="14" v:groupcontext="shape" transform="translate(114.875,-197)">		<title>shape15-68</title>		<desc>success/fail</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L5.8 405.75 L6.16 405.75 L154.12 405.75" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="55.6732" y="399.249" width="42.7786" height="13.0037" class="st9"></rect>		<text x="55.67" y="409" class="st12" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>成功<tspan class="st13">/</tspan>失败</text>		</g>	<g id="shape15-78" v:mid="15" v:groupcontext="shape" transform="translate(32.25,-140.75)">		<title>shape16-75</title>		<rect x="0" y="360.75" width="288.5" height="45" class="st14"></rect>	</g>	<g id="shape16-80" v:mid="16" v:groupcontext="shape" transform="translate(114.875,-156.5)">		<title>shape17-77</title>		<desc>sensorEvent</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L5.8 405.75 L6.16 405.75 L154.12 405.75" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="49.2692" y="399.75" width="55.5867" height="12.0001" class="st9"></rect>		<text x="49.27" y="408.75" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>sensorEvent</text>		</g>	<g id="shape17-87" v:mid="17" v:groupcontext="shape" transform="translate(114.875,-113.75)">		<title>shape18-84</title>		<desc>close()</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0625" cy="405.75" width="154.14" height="0"></v:textrect>		<path d="M0 405.75 L147.96 405.75 L147.96 405.75" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="62.0601" y="399.75" width="30.005" height="12.0001" class="st9"></rect>		<text x="62.06" y="408.75" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>close()</text>		</g>	<g id="shape18-94" v:mid="18" v:groupcontext="shape" transform="translate(114.875,-95.7501)">		<title>shape19-91</title>		<path d="M0 405.75 L5.8 405.75 L6.16 405.75 L154.12 405.75" class="st11"></path>	</g>	<g id="shape20-99" v:mid="20" v:groupcontext="shape" transform="translate(72.1251,-23.75)">		<title>shape21-101</title>		<desc>Application</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="42.75" cy="392.25" width="85.51" height="27"></v:textrect>		<rect x="0" y="378.75" width="85.5001" height="27" class="st2"></rect>		<text x="18.75" y="396.15" class="st3" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>应用程序</text>		</g>	<g id="shape21-102" v:mid="21" v:groupcontext="shape" transform="translate(202.625,-23.75)">		<title>shape22-104</title>		<desc>libSensingHubSession</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="66.375" cy="392.25" width="132.76" height="27"></v:textrect>		<rect x="0" y="378.75" width="132.75" height="27" class="st2"></rect>		<text x="6.34" y="395.85" class="st4" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>libSensingHubSession</text>		</g>	<g id="shape22-105" v:mid="22" v:groupcontext="shape" transform="translate(29.375,-72.125)">		<title>shape23-107</title>		<desc>delete ISession*</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="41.625" cy="400.687" width="83.26" height="10.125"></v:textrect>		<rect x="0" y="395.625" width="83.25" height="10.125" class="st15"></rect>		<text x="9.11" y="403.94" class="st12" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>删除<tspan class="st13"> </tspan><tspan class="st13">ISession</tspan><tspan class="st13">*</tspan></text>		</g>	<g id="shape23-111" v:mid="23" v:groupcontext="shape" transform="translate(23.75,537.437) scale(1,-1)">		<title>shape26-110</title>		<desc>opt</desc>		<v:userdefs>			<v:ud v:nameu="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CTypeTopRightSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotLeftSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockHoriz" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockVert" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockDiag" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="TopLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="TopRightOffset" v:prompt="" v:val="VT0(0):26"></v:ud>			<v:ud v:nameu="BotLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="BotRightOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="visVersion" v:prompt="" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="12.375" cy="399.844" width="24.76" height="11.8125"></v:textrect>		<path d="M0 405.75 L24.75 405.75 L24.75 399.84 L18.84 393.94 L0 393.94 L0 405.75 Z" class="st2"></path>		<text x="6.81" y="-397.44" transform="scale(1,-1)" class="st16" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>opt</text>		</g>	<g id="shape24-114" v:mid="24" v:groupcontext="shape" transform="translate(32.25,626.25) scale(1,-1)">		<title>shape27-113</title>		<desc>loop</desc>		<v:userdefs>			<v:ud v:nameu="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CTypeTopRightSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotLeftSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockHoriz" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockVert" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockDiag" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="TopLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="TopRightOffset" v:prompt="" v:val="VT0(0):26"></v:ud>			<v:ud v:nameu="BotLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="BotRightOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="visVersion" v:prompt="" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="14.625" cy="399.422" width="29.26" height="12.6562"></v:textrect>		<path d="M0 405.75 L29.25 405.75 L29.25 399.42 L22.92 393.09 L0 393.09 L0 405.75 Z" class="st2"></path>		<text x="7.06" y="-397.02" transform="scale(1,-1)" class="st16" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>loop</text>		</g>	<g id="shape25-117" v:mid="25" v:groupcontext="shape" transform="translate(50.5,-262.25)">		<title>shape28-116</title>		<desc>[perSUID]</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="22.25" cy="400.687" width="44.52" height="10.125"></v:textrect>		<rect x="0" y="395.625" width="44.5" height="10.125" class="st15"></rect>		<text x="4.69" y="403.09" class="st16" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>[perSUID]</text>		</g>	<g id="shape26-120" v:mid="26" v:groupcontext="shape" transform="translate(59.25,-173.859)">		<title>shape29-119</title>		<desc>[sensorEvent]</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="29.25" cy="400.687" width="58.51" height="10.125"></v:textrect>		<rect x="0" y="395.625" width="58.5" height="10.125" class="st15"></rect>		<text x="4.79" y="403.09" class="st16" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>[sensorEvent]</text>		</g>	<g id="shape27-123" v:mid="27" v:groupcontext="shape" transform="translate(114.3,-65.25)">		<title>shape20-68</title>		<v:userdefs>			<v:ud v:nameu="TextPos" v:val="VT0(2):26"></v:ud>			<v:ud v:nameu="Scale" v:val="VT0(1):26"></v:ud>			<v:ud v:nameu="AntiScale" v:val="VT0(1):26"></v:ud>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>			<v:ud v:nameu="msvDisableCustomConnectionPoints" v:prompt="" v:val="VT0(1):5"></v:ud>		</v:userdefs>		<path d="M0 392.25 L31.95 392.25 A6.75 6.75 0 0 1 38.7 399 A6.75 6.75 0 0 1 31.95 405.75 L6.16 405.75 L0 405.75" class="st17"></path>	</g></g>
</svg>

QSH 客户端 API 工作流

- **getSession**

    要与 QSH 交互，传感器应用客户端必须通过调用 `getSession()` API 创建接口会话，如图所示。如果成功创建接口会话，则会向客户端返回 `ISession*` 对象。
- **Open、Close、SetCallback 和 SendRequest**

    使用 `getSession()` API 创建的接口以 *once\_per\_session* 为基础运行。此接口允许应用程序使用 QSH 客户端 API，例如 `open()`、`close()`、`setCallback()` 和 `sendRequest()`，直到使用 `close()` 和 `delete()` API 显式删除会话。

    建立接口会话后，应用程序或客户端代码可以通过调用 `open()` API 来打开传感器会话。与 `getSession()` 类似，`open()` API 也是在 *once\_per\_session* 基础上调用。此外，关于给定的 SUID，`setCallback()` 和 `sendRequest()` API 会被调用一次。

### 消息

所有请求和响应消息都遵循以下流程：

1. 通过 `sendRequest()` API 发送 `sns_client_request_msg` 请求消息。

    - 此消息的唯一字段是净荷，它是一个不透明的字节数组。该字段由协议缓存编码的 `sns_client_request_msg` 消息填充。
2. 收到 `sns_client_resp_msg` 响应消息。

    - 客户端管理器在收到请求后立即发送此响应消息。
    - 对请求执行最少量的处理。客户端管理器确定 `sns_client_request_msg` 消息是否已相应编码以及目标 SUID 是否可用。
3. 接收 `sns_client_event_msg` 消息类型的一个或多个事件。

    - 按照 `setCallback` API 中的指定，事件消息在事件回调函数中接收。
    - 每个消息都包含一个 SUID。
    - 事件消息可能包含一个或多个逻辑传感器示例，这些示例都编码在单个 `sns_client_event_msg` 消息中。

### 协议缓存

QSH 客户端请求和事件消息是包含协议缓存编码消息的不透明内存缓存。客户端可以用多种编程语言生成这些消息，然后将编码的字节数据流复制到 `sns_client_request_msg` 消息中。同样，客户端可以从 `sns_client_report_ind_msg` 消息中复制编码的消息并单独对其进行解码。

有关协议缓存的更多信息，参见[协议缓存](https://developers.google.com/protocol-buffers/)和 [nanopb](https://github.com/nanopb/nanopb)。

### 客户端管理器

传感器客户端管理器位于 QSH 内，用于监管所有通信过程。客户端管理器有以下作用：

- **转换传入请求**：客户端管理器接收传入请求并将其转换为 QSH 可以理解的格式。转换涉及将请求转换为特定的请求消息。
- **转换传出指示**：当客户端管理器收到来自 QSH 的事件消息时，客户端管理器将事件消息转换为传出指示。通过转换可确保消息的格式在 QSH 外部可理解。
- **保证批处理选项**：如果客户端指定了某些批处理选项，则客户端管理器负责确保满足这些选项。它检查数据是否以客户端指定的方式分组和发送。

    关于客户端管理器的更多信息，请参阅 `<workspace>/build-qcom-wayland/workspace/sources/sensinghub/sensing-hub/apis/proto/sns_client.proto` 文件。
- **SUID**：SUID 是一个整数，用于唯一标识 QSH 提供的单个传感器。客户端将此 ID 视为在启动时随机生成的 ID。客户端不会假定 ID 重复或从数字本身派生任何信息。

    例如，如果 QSH 有两种引力算法可用，则每种算法都有自己唯一的 SUID。这种唯一的 ID 分配也适用于物理传感器。如果物理传感器模型的硬件在设备上多次存在，则每个硬件都有自己的 SUID。

    有关系统上可用传感器的完整列表，客户端可以向 SUID 传感器发送请求。
- **客户端请求**：客户端管理器的所有传入请求均使用 `sns_client_request_msg` 作为最外面的协议缓存消息。此消息包含以下字段：

    - SUID：用作请求消息的目标地址。所有请求消息均发送到有效的 SUID 进行处理；否则，客户端管理器将拒绝这些消息。
    - msg\_id：包含的编码请求的数字标识符在 `sns_std_request::payload` 消息中。例如，传感器可能支持数据流启用的请求消息和数据刷新请求消息。这两条消息的格式不同，此字段指示目标传感器如何解释请求。消息 ID 在传感器支持的所有消息中始终是唯一的。但是，两个不同的传感器可能会对不同的消息类型使用特定的 ID。

因此，简单来说，`sns_client_request_msg` 消息就像一个特殊的信封，将请求传送到正确的传感器并告诉它该做什么。

> 
> 
> 例如，
> 
> - **消息类型** — 有两种消息类型：
> 
> 
> 
> > 
> > 
> > - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG`：用于从客户端到传感器的标准数据流请求。
> >     - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT`：用于表示来自数据源传感器的标准传感器事件。
> - **请求** — 客户端发送到传感器的信息包。它包含了传感器完成其工作所需的所有详细信息。`sns_std_request::payload` 字段对应于消息 ID 并且具有特定于传感器的配置。
> 
> 
> 
> > 
> > 
> > 有关详细信息，参见特定于传感器的 proto。
> - **重采样器配置** — 在客户端想要更改传感器对数据进行采样的速率时使用。以下是进行重采样器配置的两种方法：
> 
> 
> 
> > 
> > 
> > - `SNS_RESAMPLER_RATE_FIXED`：客户端需要以特定速率提供数据。例如，如果客户端希望获取 200 Hz 的数据，而物理传感器支持 240 Hz 的数据流，则示例将插值到 200 Hz。
> >     - `SNS_RESAMPLER_RATE_MINIMUM`：客户端希望以一定的最低速率提供数据。例如，如果客户端希望以 200 Hz 的频率获取数据，而物理传感器支持以 240 Hz 的频率进行数据流传输，则以 240 Hz 的频率发送示例。
> - **阈值配置** — 当客户端仅在满足特定条件的情况下才需要数据时使用。共有四个种类型的条件：
> 
> 
> 
> > 
> > 
> > - `SNS_THRESHOLD_TYPE_RELATIVE_VALUE` 提供的阈值，是当前值与上次报告的超出配置阈值的值这二者之间的差值。
> >     - `SNS_THRESHOLD_TYPE_RELATIVE_PERCENT` 提供的阈值是当前值与上次报告值之间的差值，并以上次报告值的百分比进行表示，其中百分比即为配置的阈值。
> >     - `SNS_THRESHOLD_TYPE_ABSOLUTE` 提供的阈值是固定配置的值。
> >     - `SNS_THRESHOLD_TYPE_ANGLE` 提供的阈值是四元数传感器的电流与上次报告的四元数之间夹角（以弧度为单位）。
> - **Suspend 配置** — 指定在处理器 Suspend 时系统的行为方式。
> 
>     - `client_proc_type` 是客户端所在的处理器。如果此处理器上的任何客户端请求刷新（完全发送数据），则该处理器上的所有客户端都将获得刷新数据。
>     - `delivery_type` 是关于是否在处理器 Suspend 时发送事件。
> 
>         - `SNS_STD_DELIVERY_WAKEUP`：每当事件可用时（以采样率或批处理周期）发送事件。如果请求的 `batch_period` 大于系统容量，则在容量耗尽时发送所有数据。启用此选项后，`flush_period` 实际上会被忽略，因为未发送的批处理数据没有机会在缓存中累积。
>         - `SNS_STD_DELIVERY_NO_WAKEUP`：仅当客户端处理器未 Suspend 时才发送事件；否则，将数据批处理到刷新期为止。目标处理器退出 Suspend 后，将发送所有 Suspend 的事件。
>     - `nowakeup_msg_ids` 是不会唤醒客户端处理器的消息 ID 列表。所述消息 ID 不具有唤醒功能。仅当存在任何其他具有唤醒功能的事件时，才会发送它们。
> 
> 
> 
>     有关详细信息，请参阅 `<workspace>/build-qcom-wayland/workspace/sources/sensinghub/sensing-hub/apis/proto/sns_client.proto` 文件。

- **批处理**：在 `sns_client_request_msg::sns_std_request` 消息中，客户端可以指定接收请求数据的方式和时间。

    `sns_std_request` 具有以下字段：

    - `batching::batch_period`：一个无符号整数值，表示批处理时间（以微秒为单位）。客户端可以假定已为给定的 `batch_period`（以微秒为单位）注册了一个计时器。自上次计时器过期到下一次计时器触发之前所生成的所有事件都将保存。此期限即为客户端指定的最长期限。在某些并发方案中，事件可能会以更快的速率（较小的批处理周期）传递到客户端。客户端可以随时发送刷新请求，以指示客户端管理器发送所有批处理数据。默认情况下，批处理处于禁用状态。
    - `batching::flush_period`：无符号整数值，以微秒为单位。此字段向客户端管理器或物理传感器提供提示，说明如果数据未发送到客户端，则必须批处理多少历史数据。换言之，客户端管理器可能会以微秒为单位删除早于 `flush_period` 的数据。由于系统内存限制，有效刷新周期可能较小，在并发情况下可能较长。此字段是可选的，如果未设置，则默认为 `batch_period`，即仅保留一批数据。如果设置了该字段，则 `flush_period` 必须大于或等于 `batch_period`。
    - `batching::flush_only`：如果设置为 True，则客户端管理器仅在客户端发起刷新时发送事件。否则，它将继续批处理，直到达到 `flush_period` 为止（此时，批处理将继续，但可能会删除最早的数据）。
    - `batching::max_batch`：如果设置为 True，它将引导传感器以最大批处理容量运行。如果请求同时具有 `flush_only = true` 和 `max_batch = true`，则 `flush_only` 优先。
- **客户端事件**：来自客户端管理器的所有传出指示均使用 `sns_client_event_msg` 作为位于 `sns_client_report_ind_msg` 的净荷字段内的最外层协议缓存编码消息。

    `sns_client_event_msg` 消息有几个字段：

    - SUID：与数据源事件关联。如果客户端向单个连接上的多个 SUID 发送请求，则此消息仅包含一个 SUID 的事件。来自其他 SUID 的事件在单独的指示消息中传递。
    - `events::msg_id`：唯一标识关联的事件消息。
    - `events::timestamp`：与此事件关联的基于 QTimer 时钟计时单位的时间戳。对于大多数事件，传感器会设置时间戳，该时间戳是指在传感器硬件中创建物理示例的时间。对于框架生成的事件（如配置更新或错误事件），此时间戳是指创建事件的时间。
    - `events::payload`：动态长度净荷，包含来自传感器的实际数据/事件。使用特定于传感器的 proto 缓存单独解码此净荷。
- **消息净荷**：传感器特定的请求或事件在 `sns_client_request_msg::sns_std_request::payload` 和 `sns_client_event_msg::sns_client_event::payload` 消息中提及。这些消息字段包含协议缓存编码的消息，其字段特定于该消息 ID，或者可能为空，并且没有字段。

    客户端使用与其通信的传感器关联的 `.proto` 文件。每种传感器类型均有相应的 `.proto` 文件。例如，`sns_accel.proto` 描述了如何启用加速计流。此外，每个传感器都会发布其 `.proto` 文件列表作为其属性的一部分。关于详细信息，请参阅[表：传感器属性](https://docs.qualcomm.com/doc/80-70017-7SC/topic/samples.html#table-n14-1hh-p1c-monicapa-03-01-24-940-43-733)。

    - **数据类型**：每个传感器均会通告一个数据类型属性。每种数据类型都与一组唯一的 `*.proto` 文件相关联，这些文件构成了该传感器专有 API。所有相同类型的传感器必须支持一组最少的请求和事件消息。它们可以定义和使用更多的该传感器专有的可选消息。每个传感器都会发布其 `.proto` 文件的完整列表作为其属性的一部分。
    - **标准化消息**：任何客户端都可以向任何传感器发送一组 Qualcomm 定义的标准化消息。这些消息在 `sns_std.proto` 文件中定义。

        - `SNS_STD_MSGID_SNS_STD_ATTR_REQ`：查询传感器的属性列表。它返回一个事件，其 `SNS_STD_MSGID_SNS_STD_ATTR_EVENT` ID 包含所有已发布属性列表，请参阅[表：传感器属性](https://docs.qualcomm.com/doc/80-70017-7SC/topic/samples.html#table-n14-1hh-p1c-monicapa-03-01-24-940-43-733)。客户端还可以在发布新属性或更新属性时注册通知。

            - `sns_std_attr_req` 具有以下字段：

                - `register_updates`: 如果设置为 True，则每当传感器属性发生更改时，客户端都会通过 `sns_std_attr_event` 收到通知。
            - `sns_std_attr_event` 具有以下字段：

                - `attributes`：传感器发布的所有属性的列表。在响应 `sns_std_attr_req` 或对已注册传感器的属性更改时发送。
        - `SNS_STD_MSGID_SNS_STD_FLUSH_REQ`：强制立即将来自此传感器的所有批处理数据发送到客户端。此命令强制系统上适用的硬件和软件缓存刷新所有存在的数据。

            例如，将此请求发送到加速度计传感器会导致刷新物理 FIFO 以及客户端管理器当前具有的任何示例。如果刷新请求是针对内部使用加速度计和陀螺仪数据的算法（例如游戏旋转矢量），则加速度计和陀螺仪硬件 FIFO 都会刷新。
        - `SNS_CLIENT_MSGID_SNS_CLIENT_DISABLE_REQ`：禁用此传感器的活动请求。例如，客户端向加速度计传感器发送 `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG` 消息以启用数据流动。稍后，发送 `DISABLE_REQ` 将取消数据流请求，并且此客户端的加速计数据流将停止。
        - `SNS_STD_MSGID_SNS_STD_FLUSH–EVENT`：对刷新请求的响应。它表示没有与刷新请求对应的其他事件。
        - `SNS_STD_MSGID_SNS_STD_ERROR–EVENT`：由传感器/实例或框架生成的错误事件。

            有关详细信息，请参阅 `<workspace>/build-qcom-wayland/workspace/sources/sensinghub/sensing-hub/apis/proto/sns_client.proto` 文件。
    - **标准化传感器消息**：客户端请求中描述的消息适用于所有传感器。除了客户端请求中所描述的消息之外，还可以使用 Qualcomm 推荐的标准化消息。这些建议是可选的，您可以选择定义自己的请求和事件消息。

        - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG`：请求为以下项启用数据流的消息：

            - 任何物理传感器，例如加速度计、陀螺仪和地磁传感器。
            - 部分算法，例如旋转矢量、重力和线性加速度。
        - `SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG`：请求为更改类型传感器启用数据流的消息，例如，proximity、ambient\_light 和 step\_detect。
        - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_PHYSICAL_CONFIG_EVENT`：所有物理传感器在处理客户端请求时发送的事件。它指示客户端必须期望的数据流，例如，传感器生成示例的速率。
        - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT`：传感器产生的数据示例。

        有关详细信息，请参阅 `sns_std_sensor.proto` 文件。
    - **SUID 查找传感器**：客户端可以在 SUID 查找传感器中查询与特定数据类型关联的 SUID 列表。`sns_suid_req` 消息指定数据类型，客户端接收所有匹配的 SUID。空数据类型字符串会导致接收系统上所有 SUID。

        例如，如果客户端将 *accel* 指定为数据类型，则它们会收到其传感器提供 *accel* 类型数据的所有 SUID。此外，如果客户端想要在找到新匹配项时接收通知，可以通过 `register_updates` 字段进行指示。客户端可以在 `sns_suid_req` 消息之后发送一个属性请求 (`sns_std_attr_req`)，以决定哪些可用的*加速度*传感器适合该客户端。

        SUID 查找传感器具有自己的 SUID，该 SUID 是常量并发布在 `sns_suid.proto` 文件中（在所有其他传感器中保持唯一）。

        `sns_suid_req` 消息包含以下字段：

表：SUID请求

        | 字段 | 强制或可选 | 数据类型 | 说明 |
        | --- | --- | --- | --- |
        | `data_type` | 必选 | 字符串 | 要查询 SUID 的传感器的数据类型 |
        | `register_updates` | 选填 | Boolean | 注册以获取更新，了解公布 `data_type` 字段的 SUID 列表 |
        | `default_only` | 选填 | Boolean | 可以通过注册表为每种数据类型配置一个默认传感器。<br><br><br><br>> <br>> <br>> <ul class="simple"><br>> <li><p>如果 <code class="docutils literal notranslate"><span class="pre">default_only</span></code> 字段设置为 Ture，且：</p><ul><br>> <li><p>显式配置了数据类型的默认值，则仅通过 SUID 事件发送默认的传感器 SUID（如有）</p></li><br>> <li><p>未显式配置数据类型的默认值，则通过 SUID 事件发送数据类型相匹配的第一个传感器的 SUID</p></li><br>> </ul><br>> </li><br>> <li><p>如果 <code class="docutils literal notranslate"><span class="pre">default_only</span></code> 字段设置为 False，则数据类型匹配的所有传感器都将在可用时发送。</p></li><br>> </ul> |

> 
> 
> 更多信息，参见 <cite>sns_suid.proto</cite> 文件和示例代码。
- **传感器属性**：每个传感器都会发布一系列属性，每个属性都由一个数字标识符表示。这些属性提供有关传感器功能及其接受作为输入的值范围的信息。

    下表列出了几个重要属性：

表：传感器属性

    | 属性 ID | 属性名称 | 强制与否 | 数据类型 | 说明 |
    | --- | --- | --- | --- | --- |
    | 0 | `SNS_STD_SENSOR_ATTRID_NAME` | 是 | 字符串 | 易读的传感器名称。 |
    | 1 | `SNS_STD_SENSOR_ATTRID_VENDOR` | 是 | 字符串 | 易读的供应商名称。 |
    | 2 | `SNS_STD_SENSOR_ATTRID_TYPE` | 是 | 字符串 | 传感器 proto 文件中所定义的供此传感器使用的数据类型。 |
    | 3 | `SNS_STD_SENSOR_ATTRID_AVAILABLE` | 是 | Boolean | 指示此传感器是否可用于客户端。 |
    | 4 | `SNS_STD_SENSOR_ATTRID_VERSION` | 是 | 整型 | <ul class="simple"><br><li><p>表示为 major[31:16].minor[15:8].revision[7:0] 的 64 位整数值，指示传感器版本。</p></li><br><li><p>十六进制示例：major：0x0002 minor：0x00 revision：0x36。</p></li><br><li><p>DRIVER_VERSION 0x00020036。</p></li><br></ul> |
    | 5 | `SNS_STD_SENSOR_ATTRID_API` | 是 | 字符串 | 列出该传感器使用的各个 `.proto` 文件名；更多 `.proto` 依赖项可以在同一个 proto 文件中指定为导入项，以用于自动化测试的目的。 |
    | 6 | `SNS_STD_SENSOR_ATTRID_RATES` | 否 | 浮点 | 传感器支持的采样率。 |
    | 7 | `SNS_STD_SENSOR_ATTRID_RESOLUTIONS` | 否 | 浮点 | 传感器支持的样品分辨率。 |
    | 8 | `SNS_STD_SENSOR_ATTRID_FIFO_SIZE` | 否 | 整型 | 支持的 FIFO 深度（示例数）。 |
    | 9 | `SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT` | 否 | 整型 | 有源电流阵列（以 μA 为单位）。 |
    | 10 | `SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT` | 否 | 整型 | 非活动电流（以 μA 为单位）。 |
    | 11 | `SNS_STD_SENSOR_ATTRID_RANGES` | 否 | 浮点 | 传感器支持的工作范围。 |
    | 12 | `SNS_STD_SENSOR_ATTRID_OP_MODES` | 否 | 字符串 | 定义传感器支持的工作模式的字符串数组。<br><br><br>例如，[LPM, HIGH\_PERF, NORMAL, OFF]. |
    | 13 | `SNS_STD_SENSOR_ATTRID_DRI` | 否 | Boolean | 表示传感器支持 DRI 还是 IBI：<br><br><br><br>> <br>> <br>> <ul class="simple"><br>> <li><p>True = DRI</p></li><br>> <li><p>False = IBI</p></li><br>> </ul> |
    | 14 | `SNS_STD_SENSOR_ATTRID_STREAM_SYNC` | 否 | Boolean | 表示传感器是否支持同步数据流。 |
    | 15 | `SNS_STD_SENSOR_ATTRID_EVENT_SIZE` | 否 | 整型 | <ul class="simple"><br><li><p>此传感器生成的数据事件（协议缓存编码）的大小（以字节为单位）。</p></li><br><li><p>对于物理和虚拟传感器，此值是指其传感器示例的大小</p></li><br><li><p>供 HAL 用于确定最大批处理容量。</p></li><br></ul> |
    | 16 | `SNS_STD_SENSOR_ATTRID_STREAM_TYPE` | 是 | 整型 | 表示传感器支持的数据流类型：<br><br><br><br>> <br>> <br>> <ul class="simple"><br>> <li><p>0 = 连续定期采样</p></li><br>> <li><p>1 = 更改时</p></li><br>> <li><p>2 = 单路输出（单次）</p></li><br>> </ul> |
    | 17 | `SNS_STD_SENSOR_ATTRID_DYNAMIC` | 否 | Boolean | 指定此传感器是否为动态（在 runtime 中连接/断开）。 |
    | 18 | `SNS_STD_SENSOR_ATTRID_HW_ID` | 否 | 整型 | 区分同一硬件的多个传感器。 |
    | 19 | `SNS_STD_SENSOR_ATTRID_RIGID_BODY` | 否 | 整型 | 放置传感器的刚体。<br><br><br><br>> <br>> <br>> <ul class="simple"><br>> <li><p>0 = 传感器硬件位于显示屏侧</p></li><br>> <li><p>1 = 传感器硬件位于键盘侧</p></li><br>> <li><p>2 = 传感器硬件安装在外部设备上</p></li><br>> </ul> |
    | 21 | `SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR` | 否 | Boolean | <ul class="simple"><br><li><p>True，限于物理传感器。</p></li><br><li><p>False，限于虚拟传感器。</p></li><br></ul> |
    | 22 | `SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR_TESTS` | 否 | 整型 | 使用 `sns_physical_sensor_test_type` 中的枚举值表示支持的物理传感器测试。 |
    | 23 | `SNS_STD_SENSOR_ATTRID_SELECTED_RESOLUTION` | 否 | 浮点 | 每个动态范围值的测量分辨率。 |
    | 24 | `SNS_STD_SENSOR_ATTRID_SELECTED_RANGE` | 否 | Float[2] | 传感器支持的动态范围选项。有关默认选项，参见要求规范。 |
    | 25 | `SNS_STD_SENSOR_ATTRID_ADDITIONAL_LOW_LATENCY_RATES` | 否 | 浮点 | 低延迟操作的其他采样率，以 Hz 为单位。这些采样率适用于专用的低延迟客户端，扩展了 `SNS_STD_SENSOR_ATTRID_RATES` 属性中发布的速率。<br><br><br>专用内部客户端必须使用这些更高的数据传输速率，因为它们可能会影响系统性能。 |
    | 26 | `SNS_STD_SENSOR_ATTRID_PASSIVE_REQUEST` | 否 | Boolean | 如果传感器支持被动请求，则为 true，否则为 false。如果传感器不支持被动请求，则必须将所有请求视为主动请求。 |
    | 29 | `SNS_STD_SENSOR_ATTRID_TRANSPORT_MTU_SIZE` | 否 | 整型 | 传输传感器的 MTU 大小（以字节为单位）。 |
    | 30 | `SNS_STD_SENSOR_ATTRID_HLOS_INCOMPATIBLE` | 否 | Boolean | 如果传感器与受支持数据类型的 high-level 操作系统 (HLOS) 规范不兼容，则为 True。 |
    | 31 | `SNS_STD_SENSOR_ATTRID_SERIAL_NUM` | 否 | 字符串 | 传感器序列号。 |
    | 32 | `SNS_STD_SENSOR_ATTRID_TECH_USED` | 否 | 整数数组 | 使用的技术列表。关于更多信息，请参阅 `sns_std_type.proto` 文件中的 `sns_tech`。 |

> 
> 
> 更多信息，参见 <cite>sns_std_sensor.proto</cite> 文件和示例代码。Proto 文件位于设备上的 `/etc/sensors/proto/` 位置。

## QSH 示例客户端调用流程和 QSH 客户端 API 与 QSH 的用法

提供了一个名为 `SessionClient` 的示例程序作为参考，以演示 QSH 客户端 API 用法。此示例程序默认生成于设备上的 `/usr/bin` 目录中。关于完整的示例代码，请参阅 `<workspace>/build-qcom-wayland/workspace/sources/sensinghub/sensing-hub/examples/SessionClient/SessionClient.cpp` 文件。

下图显示了进行加速度计传感器数据流的 call flow 以及 QSH 客户端 API 的使用情况。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- 由 Microsoft Visio, SVG Export 生成 callflow-to-stream-a-given-sensor.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="5.01042in" height="5.33333in" viewbox="0 0 360.75 384" xml:space="preserve" color-interpolation-filters="sRGB" class="st19"><v:documentproperties v:langid="2052">	<v:userdefs>		<v:ud v:nameu="msvNoAutoConnect" v:val="VT0(1):26"></v:ud>	</v:userdefs></v:documentproperties>
<style>.svg-2 .st1 { fill: #f7f8fa; stroke: none; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.75 }
.svg-2 .st2 { fill: #f7f8fa; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.999999 }
.svg-2 .st3 { fill: #000000; font-family: SimHei; font-size: 1.00001em }
.svg-2 .st4 { fill: #000000; font-family: Arial; font-size: 1.00001em }
.svg-2 .st5 { fill: none }
.svg-2 .st6 { stroke: #000000; stroke-dasharray: 7, 5; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.999999 }
.svg-2 .st7 { marker-end: url("#mrkr5-20"); stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.999999 }
.svg-2 .st8 { fill: #000000; fill-opacity: 1; stroke: #000000; stroke-opacity: 1; stroke-width: 0.28409078197635 }
.svg-2 .st9 { fill: #ffffff; stroke: none; stroke-linecap: butt; stroke-width: 7.2 }
.svg-2 .st10 { fill: #000000; font-family: Arial; font-size: 0.833336em }
.svg-2 .st11 { marker-start: url("#mrkr5-28"); stroke: #000000; stroke-dasharray: 7, 5; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.999999 }
.svg-2 .st12 { fill: none; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.999999 }
.svg-2 .st13 { fill: #000000; font-family: SimHei; font-size: 0.833336em }
.svg-2 .st14 { font-family: Arial; font-size: 1em }
.svg-2 .st15 { marker-end: url("#mrkr5-20"); stroke: #000000; stroke-linecap: butt; stroke-width: 0.999999 }
.svg-2 .st16 { fill: none; stroke: none; stroke-linecap: round; stroke-linejoin: round; stroke-width: 0.75 }
.svg-2 .st17 { fill: #000000; font-family: Arial; font-size: 0.666664em }
.svg-2 .st18 { font-family: SimHei; font-size: 1em }
.svg-2 .st19 { fill: none; fill-rule: evenodd; font-size: 12px; overflow: visible; stroke-linecap: square; stroke-miterlimit: 3 }</style>
<defs id="Markers">	<g id="lend5">		<path d="M 2 1 L 0 0 L 1.98117 -0.993387 C 1.67173 -0.364515 1.67301 0.372641 1.98465 1.00043 " style="stroke:none"></path>	</g>	<marker id="mrkr5-20" class="st8" v:arrowtype="5" v:arrowsize="2" v:setback="0" refx="-0" orient="auto" markerunits="strokeWidth" overflow="visible">		<use xlink:href="#lend5" transform="scale(-3.520001575001,-3.520001575001) "></use>	</marker>	<marker id="mrkr5-28" class="st8" v:arrowtype="5" v:arrowsize="2" v:setback="0" refx="0" orient="auto" markerunits="strokeWidth" overflow="visible">		<use xlink:href="#lend5" transform="scale(3.520001575001) "></use>	</marker></defs><g v:mid="0" v:index="1" v:groupcontext="foregroundPage">	<title>Page-1</title>	<v:pageproperties v:drawingscale="1" v:pagescale="1" v:drawingunits="19" v:shadowoffsetx="8.99999" v:shadowoffsety="-8.99999"></v:pageproperties>	<g id="shape1-1" v:mid="1" v:groupcontext="shape" transform="translate(18.3752,-18.375)">		<title>shape1007-1</title>		<rect x="0" y="36.75" width="324" height="347.25" class="st1"></rect>	</g>	<g id="shape2-3" v:mid="2" v:groupcontext="shape" transform="translate(73.6252,-334.625)">		<title>shape2-3</title>		<desc>Application</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="42.7497" cy="370.5" width="85.5" height="27"></v:textrect>		<rect x="0" y="357" width="85.4999" height="27" class="st2"></rect>		<text x="18.75" y="374.4" class="st3" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>应用程序</text>		</g>	<g id="shape3-6" v:mid="3" v:groupcontext="shape" transform="translate(203,-334.625)">		<title>shape4-6</title>		<desc>libSensingHubSession</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="66.3747" cy="370.5" width="132.75" height="27"></v:textrect>		<rect x="0" y="357" width="132.75" height="27" class="st2"></rect>		<text x="6.34" y="374.1" class="st4" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>libSensingHubSession</text>		</g>	<g id="shape4-9" v:mid="4" v:groupcontext="shape" transform="translate(499.25,49.375) rotate(90)">		<title>shape5-9</title>		<path d="M0 384 L287 384 L0 384 Z" class="st5"></path>		<path d="M0 384 L287 384" class="st6"></path>	</g>	<g id="shape5-12" v:mid="5" v:groupcontext="shape" transform="translate(653.375,49.375) rotate(90)">		<title>shape6-12</title>		<path d="M0 384 L305.85 384 L0 384 Z" class="st5"></path>		<path d="M0 384 L305.85 384" class="st6"></path>	</g>	<g id="shape6-15" v:mid="6" v:groupcontext="shape" transform="translate(115.25,-316.625)">		<title>shape7-15</title>		<desc>getSession</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L147.96 384 L154.12 384" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="52.3232" y="378" width="49.4783" height="12.0001" class="st9"></rect>		<text x="52.32" y="387" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>getSession</text>		</g>	<g id="shape7-23" v:mid="7" v:groupcontext="shape" transform="translate(115.25,-298.625)">		<title>shape8-23</title>		<desc>ISession*</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L5.8 384 L6.16 384 L154.12 384" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="55.9388" y="378" width="42.2468" height="12.0001" class="st9"></rect>		<text x="55.94" y="387" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>ISession*</text>		</g>	<g id="shape8-31" v:mid="8" v:groupcontext="shape" transform="translate(24.1252,-229.875)">		<title>shape11-31</title>		<rect x="0" y="330" width="310.5" height="54" class="st12"></rect>	</g>	<g id="shape9-33" v:mid="9" v:groupcontext="shape" transform="translate(115.25,-261.375)">		<title>shape12-33</title>		<desc>get SUID using ISession*</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L147.96 384 L154.12 384" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="19.8254" y="377.498" width="114.474" height="13.0037" class="st9"></rect>		<text x="19.83" y="387.25" class="st13" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>使用<tspan class="st14"> </tspan><tspan class="st14">ISession </tspan>获取<tspan class="st14"> </tspan><tspan class="st14">SUID</tspan><tspan class="st14">*</tspan></text>		</g>	<g id="shape10-45" v:mid="10" v:groupcontext="shape" transform="translate(115.25,-243.375)">		<title>shape13-40</title>		<desc>SUID</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L5.8 384 L6.16 384 L154.12 384" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="65.1165" y="378" width="23.8917" height="12.0001" class="st9"></rect>		<text x="65.12" y="387" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>SUID</text>		</g>	<g id="shape11-52" v:mid="11" v:groupcontext="shape" transform="translate(115.25,-196.125)">		<title>shape14-47</title>		<desc>get Attributes using ISession*</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L147.96 384 L154.12 384" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="10.6502" y="377.498" width="132.824" height="13.0037" class="st9"></rect>		<text x="10.65" y="387.25" class="st13" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>使用<tspan class="st14"> </tspan><tspan class="st14">ISession </tspan>获取<tspan class="st14"> </tspan><tspan class="st14">Attributes</tspan><tspan class="st14">*</tspan></text>		</g>	<g id="shape12-64" v:mid="12" v:groupcontext="shape" transform="translate(115.25,-180.375)">		<title>shape15-54</title>		<desc>Attributes</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L5.8 384 L6.16 384 L154.12 384" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="55.9413" y="378" width="42.2419" height="12.0001" class="st9"></rect>		<text x="55.94" y="387" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>Attributes</text>		</g>	<g id="shape13-71" v:mid="13" v:groupcontext="shape" transform="translate(115.25,-112.875)">		<title>shape17-61</title>		<desc>sensorEvents</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L5.8 384 L6.16 384 L154.12 384" class="st11"></path>		<rect v:rectcontext="textBkgnd" x="46.7688" y="378" width="60.5869" height="12.0001" class="st9"></rect>		<text x="46.77" y="387" class="st10" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>sensorEvents</text>		</g>	<g id="shape14-78" v:mid="14" v:groupcontext="shape" transform="translate(115.25,-70.125)">		<title>shape20-68</title>		<v:userdefs>			<v:ud v:nameu="TextPos" v:val="VT0(2):26"></v:ud>			<v:ud v:nameu="Scale" v:val="VT0(1):26"></v:ud>			<v:ud v:nameu="AntiScale" v:val="VT0(1):26"></v:ud>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>			<v:ud v:nameu="msvDisableCustomConnectionPoints" v:prompt="" v:val="VT0(1):5"></v:ud>		</v:userdefs>		<path d="M0 370.5 L31.95 370.5 A6.75 6.75 0 0 1 38.7 377.25 A6.75 6.75 0 0 1 31.95 384 L6.16 384 L0 384" class="st15"></path>	</g>	<g id="shape15-83" v:mid="15" v:groupcontext="shape" transform="translate(72.3752,-24)">		<title>shape21-73</title>		<desc>Application</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="42.7497" cy="370.5" width="85.5" height="27"></v:textrect>		<rect x="0" y="357" width="85.4999" height="27" class="st2"></rect>		<text x="18.75" y="374.4" class="st3" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>应用程序</text>		</g>	<g id="shape16-86" v:mid="16" v:groupcontext="shape" transform="translate(203.217,-24)">		<title>shape22-76</title>		<desc>libSensingHubSession</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="66.3747" cy="370.5" width="132.75" height="27"></v:textrect>		<rect x="0" y="357" width="132.75" height="27" class="st2"></rect>		<text x="6.34" y="374.1" class="st4" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>libSensingHubSession</text>		</g>	<g id="shape17-89" v:mid="17" v:groupcontext="shape" transform="translate(29.7502,-78)">		<title>shape23-79</title>		<desc>delete ISession*</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="41.6247" cy="378.937" width="83.25" height="10.125"></v:textrect>		<rect x="0" y="373.875" width="83.2499" height="10.125" class="st16"></rect>		<text x="9.11" y="382.19" class="st13" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>删除<tspan class="st14"> </tspan><tspan class="st14">ISession</tspan><tspan class="st14">*</tspan></text>		</g>	<g id="shape18-95" v:mid="18" v:groupcontext="shape" transform="translate(24.1252,484.125) scale(1,-1)">		<title>shape26-82</title>		<desc>opt</desc>		<v:userdefs>			<v:ud v:nameu="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CTypeTopRightSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotLeftSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockHoriz" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockVert" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockDiag" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="TopLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="TopRightOffset" v:prompt="" v:val="VT0(0):26"></v:ud>			<v:ud v:nameu="BotLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="BotRightOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="visVersion" v:prompt="" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="12.3748" cy="378.094" width="24.75" height="11.8125"></v:textrect>		<path d="M0 384 L24.75 384 L24.75 378.09 L18.84 372.19 L0 372.19 L0 384 Z" class="st2"></path>		<text x="6.81" y="-375.69" transform="scale(1,-1)" class="st17" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>opt</text>		</g>	<g id="shape19-98" v:mid="19" v:groupcontext="shape" transform="translate(48.7502,-272.062)">		<title>shape28-85</title>		<desc>[refer QSH Interface]</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="34.1247" cy="378.937" width="68.25" height="10.125"></v:textrect>		<rect x="0" y="373.875" width="68.2498" height="10.125" class="st16"></rect>		<text x="5.01" y="381.54" class="st17" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>[<tspan class="st18">参见</tspan> QSH <tspan class="st18">接口</tspan>]</text>		</g>	<g id="shape20-103" v:mid="20" v:groupcontext="shape" transform="translate(25.1252,-166.875)">		<title>shape1000-88</title>		<rect x="0" y="330" width="310.5" height="54" class="st12"></rect>	</g>	<g id="shape21-105" v:mid="21" v:groupcontext="shape" transform="translate(25.1252,547.125) scale(1,-1)">		<title>shape1001-90</title>		<desc>opt</desc>		<v:userdefs>			<v:ud v:nameu="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CTypeTopRightSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotLeftSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockHoriz" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockVert" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockDiag" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="TopLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="TopRightOffset" v:prompt="" v:val="VT0(0):26"></v:ud>			<v:ud v:nameu="BotLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="BotRightOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="visVersion" v:prompt="" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="12.3748" cy="378.094" width="24.75" height="11.8125"></v:textrect>		<path d="M0 384 L24.75 384 L24.75 378.09 L18.84 372.19 L0 372.19 L0 384 Z" class="st2"></path>		<text x="6.81" y="-375.69" transform="scale(1,-1)" class="st17" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>opt</text>		</g>	<g id="shape22-108" v:mid="22" v:groupcontext="shape" transform="translate(49.7502,-209.062)">		<title>shape1002-93</title>		<desc>[refer QSH Interface]</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="33.6247" cy="378.937" width="67.25" height="10.125"></v:textrect>		<rect x="0" y="373.875" width="67.2498" height="10.125" class="st16"></rect>		<text x="4.51" y="381.54" class="st17" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>[<tspan class="st18">参见</tspan> QSH <tspan class="st18">接口</tspan>]</text>		</g>	<g id="shape23-113" v:mid="23" v:groupcontext="shape" transform="translate(25.1252,-99.3749)">		<title>shape1003-96</title>		<rect x="0" y="330" width="310.5" height="54" class="st12"></rect>	</g>	<g id="shape24-115" v:mid="24" v:groupcontext="shape" transform="translate(25.1252,614.625) scale(1,-1)">		<title>shape1004-98</title>		<desc>opt</desc>		<v:userdefs>			<v:ud v:nameu="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CTypeTopRightSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotLeftSnip" v:prompt="" v:val="VT0(1):5"></v:ud>			<v:ud v:nameu="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockHoriz" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockVert" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="CornerLockDiag" v:prompt="" v:val="VT0(0):5"></v:ud>			<v:ud v:nameu="TopLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="TopRightOffset" v:prompt="" v:val="VT0(0):26"></v:ud>			<v:ud v:nameu="BotLeftOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="BotRightOffset" v:prompt="" v:val="VT0(0):1"></v:ud>			<v:ud v:nameu="visVersion" v:prompt="" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="12.3748" cy="378.094" width="24.75" height="11.8125"></v:textrect>		<path d="M0 384 L24.75 384 L24.75 378.09 L18.84 372.19 L0 372.19 L0 384 Z" class="st2"></path>		<text x="6.81" y="-375.69" transform="scale(1,-1)" class="st17" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>opt</text>		</g>	<g id="shape25-118" v:mid="25" v:groupcontext="shape" transform="translate(49.7502,-141.563)">		<title>shape1005-101</title>		<desc>[refer QSH Interface]</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="33.6247" cy="378.937" width="67.25" height="10.125"></v:textrect>		<rect x="0" y="373.875" width="67.2498" height="10.125" class="st16"></rect>		<text x="4.51" y="381.54" class="st17" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>[<tspan class="st18">参见</tspan> QSH <tspan class="st18">接口</tspan>]</text>		</g>	<g id="shape26-123" v:mid="26" v:groupcontext="shape" transform="translate(115.25,-128.625)">		<title>shape1006-104</title>		<desc>Start Streaming using SUID</desc>		<v:userdefs></v:userdefs>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="77.0622" cy="384" width="154.13" height="0"></v:textrect>		<path d="M0 384 L147.96 384 L154.12 384" class="st7"></path>		<rect v:rectcontext="textBkgnd" x="17.3378" y="377.498" width="119.449" height="13.0037" class="st9"></rect>		<text x="17.34" y="387.25" class="st13" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>使用<tspan class="st14"> </tspan><tspan class="st14">SUID </tspan>开始数据流传输</text>		</g></g>
</svg>

调用流程为指定传感器创建数据流

在此示例中，不同的传感器会话用于 SUID 查询、属性查询和数据流活动。同一会话可用于所有活动，但必须适当地处理同步。

1. **SUID 查询**检索指定传感器的 SUID：

    1. 通过使用新的 `sessionFactory()` 类调用 `getSession()` API 来创建 SUID 接口。对于任何用例而言，请求 SUID 是获取所请求数据类型的 SUID 的第一个请求，且非常重要。

/* Create a new ISession for UID discovery */
             sessionFactory* factory = new sessionFactory();
             if(nullptr == factory){
               printf("failed to create factory instance");
               return false;
             }
             ISession* suidSession = factory->getSession();
             if(nullptr == suidSession){
               printf("failed to create uid session");
               return false;
             }
            Copy to clipboard
    2. 通过调用 `open()` API 打开创建的会话接口。

/* Open the suidSession */
              int ret = suidSession->open();
              if(-1 == ret){
                printf("failed to open ISession for uid query");
                return false;
              }
            Copy to clipboard
    3. 通过调用 `setCallBacks()` API 并处理 SUID 活动的响应/事件/错误来设置回调。

/* Set callbacks for the session for 'uid' */
              ret = suidSession->setCallBacks(uid, suidResp, nullptr, suidEvent);
              if(-1 == ret)
                 printf("all callbacks are null, no need to register it");
            Copy to clipboard
    4. 通过调用 `sendRequest()` API，为给定数据类型的 SUID 创建并发送 pb 编码的请求消息。

/*
               * Create SUID request message
               * (Please refer sns_client.proto and sns_suid.proto for more details)
               * */
              string pb_req_encoded = "";
              sns_suid_req pb_suid_req;
              pb_suid_req.set_data_type(sensorName);
              pb_suid_req.set_register_updates(true);
            sns_client_request_msg pb_req_msg;
            pb_req_msg.set_msg_id(SNS_SUID_MSGID_SNS_SUID_REQ);
            ..
            string pb_req_msg_encoded;
              pb_req_msg.SerializeToString(&pb_req_msg_encoded);
              /* send proto encoded message to sensing-hub using the opened session */
              unique_lock<mutex> respLock(respMutex);
              ret = suidSession->sendRequest(uid, pb_req_msg_encoded);
              if(0 != ret){
                printf("Error in sending uid discovery request");
                return false;
              }
            Copy to clipboard
    5. 通过调用 `close()` API 关闭会话，并在收到请求数据类型的 SUID 事件后将其删除。

/* Close and delete the session once suids are received */
              suidSession->close();
              delete suidSession;
              delete factory;
            Copy to clipboard
2. **属性请求**检索指定传感器的属性：

    1. 通过使用新的 `sessionFactory()` 类调用 `getSession()` 为属性创建接口会话。对于任何用例而言，请求属性对于获取所请求数据类型的功能非常重要。

/* Create a new ISession for attribute query */
              sessionFactory* factory = new sessionFactory();
              if(nullptr == factory){
                printf("failed to create factory instance");
                return false;
              }
            
               ISession* attributeSession = factory->getSession();
              if(nullptr == attributeSession){
                printf("failed to create attribute session");
                return false;
              }
            Copy to clipboard
    2. 通过调用 `open()` API 打开创建的会话接口。

/* open the attributeSession session */
              int ret = attributeSession->open();
              if(-1 == ret){
                printf("failed to open ISession for attribute query");
                return false;
            Copy to clipboard
    3. 通过调用 `setCallBacks()` 并处理属性活动的响应/事件/错误来设置回调。

for (const suid& uid : suidList) {
                /* set callbacks for the session for 'uid' */
                int ret = attributeSession->setCallBacks(uid, attributeResp, nullptr, attributeEvent);
                if(-1 == ret)
                     printf("all callbacks are null, no need to register it");
            Copy to clipboard
    4. 通过调用 `sendRequest()` API，为给定数据类型的属性创建并发送 pb 编码的配置请求。

/* create pb-encoded config request message to be sent for attribute query */
                sns_client_request_msg pb_req_msg;
                pb_req_msg.set_msg_id(SNS_STD_MSGID_SNS_STD_ATTR_REQ);
                pb_req_msg.mutable_request()->clear_payload();
                pb_req_msg.mutable_suid()->set_suid_high(uid.high);
            ..
            ..
            /* send proto encoded message to sensing-hub using the opened session */
                unique_lock<mutex> respLock(respMutex);
                ret = attributeSession->sendRequest(uid, pb_req_msg_encoded);
            Copy to clipboard
    5. 在收到请求数据类型的属性事件后，通过调用 `close()` API 来关闭会话。

/* close and delete the session once all attributes are received */
              attributeSession->close();
              delete attributeSession;
              delete factory;
            Copy to clipboard
3. **传感器数据流**会进行传感器数据流传输并接收数据事件：

    1. 通过使用新的 `sessionFactory()` 类调用 `getSession()`，创建用于传感器数据流的接口会话。在这里，对于任何用例，请求传感器数据是请求数据类型的最后阶段。

sessionFactory()class.
            
            /* create a new ISession for streaming activity */
              sessionFactory* factory = new sessionFactory();
              if(nullptr == factory){
                printf("failed to create factory instance");
                return false;
              }
              ISession* streamingSession = factory->getSession();
              if(nullptr == streamingSession){
                printf("failed to create streaming session");
                return false;
              }
            Copy to clipboard
    2. 通过调用 `open()` API 打开创建的会话接口。

/* open the streamingSession session */
            int ret = streamingSession->open();
            if(-1 == ret){
              printf("failed to open ISession for attribute query");
              return false;
            Copy to clipboard
    3. 通过调用 `setCallBacks()` 并处理用于数据流活动的响应/事件/错误来设置回调。

for (const suid& uid : suidList){
                /* set callbacks for the session for 'uid' */
                int ret = streamingSession->setCallBacks(uid, dataResp, dataError, dataEvent);
                if(-1 == ret)
                  printf("all callbacks are null, no need to register it");
            Copy to clipboard
    4. 通过调用 `sendRequest()` API 创建并发送 pb 编码的配置请求，以对给定数据类型的传感器进行数据流传输，最终启用请求的传感器。

/* create pb-encoded config request message to be sent for streaming request */
                string pb_req_encoded = "";
                sns_std_sensor_config pb_stream_cfg;
                pb_stream_cfg.set_sample_rate(sampleRate);
                pb_stream_cfg.SerializeToString(&pb_req_encoded);
                sns_client_request_msg pb_req_msg;
                pb_req_msg.mutable_request()->mutable_batching()->set_batch_period(batchPeriod);
                pb_req_msg.set_msg_id(SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG);
            ..
            ..
            /* send proto encoded message to sensing-hub using the opened session */
                unique_lock<mutex> respLock(respMutex);
                ret = streamingSession->sendRequest(uid, pb_req_msg_encoded);
            Copy to clipboard
    5. 处理事件回调中的示例，并等待指定的测试持续时间。

void handle_event_cb(const uint8_t *data, size_t size, uint64_t time_stamp){
            if(true == deletion_started){
            printf("\nEvent coming when deletion of qmi connection started");
            return;
            }
            sns_client_event_msg pb_event_msg;
            /* Parse the pb encoded event */
            pb_event_msg.ParseFromArray(data, size);
            /* Iterate over all events in the message */
            for (int i = 0; i < pb_event_msg.events_size(); i++) {
            auto& pb_event = pb_event_msg.events(i);
            Copy to clipboard
    6. 通过调用 `sendRequest()` API 发送禁用请求来停止数据流传输活动。

pb_req_msg.set_msg_id(SNS_CLIENT_MSGID_SNS_CLIENT_DISABLE_REQ);
                pb_req_msg.mutable_suid()->set_suid_high(uid.high);
                pb_req_msg.mutable_suid()->set_suid_low(uid.low);
            ..
            ..
            /* send disable request to sensing-hub */
                int ret = streamingSession->sendRequest(uid, pb_req_msg_encoded);
            Copy to clipboard
    7. 在收到请求数据类型的数据流事件后，通过调用 `close()` API 来关闭会话。

/* close and delete the streamingSession */
              streamingSession->close();
              delete streamingSession;
              delete factory;
            Copy to clipboard

以下代码片段显示了 `SessionClient` 示例应用程序输出。它使加速度传感器具有 10 Hz 采样率和 2 s 的批处理周期，持续 10 s，并打印接收到的传感器事件。

root@qcm6490:~# SessionClient
    Streaming configuration is as follows :
            Sensor name : accel     Sample rate : 10 Hz     Batch period : 2 sec    Test duration : 10 sec

    SUID discovery response received.
    Received SUIDs for accel, number of suids received = 1
    
    SUID received - suid_low=6360260105974108950 suid_high=7037810611998542250
    Sensor suid list created
    
    requesting attributes for - suid_low=6360260105974108950 suid_high=7037810611998542250
    
    Attribute query response received.
    Attributes for - suid_low=6360260105974108950 suid_high=7037810611998542250 are :
    attribute count 0        and values are: attr_id: 16     sint: 0
    attribute count 1        and values are: attr_id: 9      sint: 50sint: 240sint: 240
    attribute count 2        and values are: attr_id: 12     std: LPM std: NORMAL std: HIGH_PERF
    attribute count 3        and values are: attr_id: 5      std: sns_accel.proto
    attribute count 4        and values are: attr_id: 0      std: icm4x6xx
    attribute count 5        and values are: attr_id: 1      std: TDK-Invensense
    attribute count 6        and values are: attr_id: 26     boolean 1
    attribute count 7        and values are: attr_id: 17     boolean 0
    attribute count 8        and values are: attr_id: 10     sint: 6
    attribute count 9        and values are: attr_id: 15     sint: 16
    attribute count 10       and values are: attr_id: 21     boolean 1
    attribute count 11       and values are: attr_id: 22     sint: 3sint: 2sint: 1
    attribute count 12       and values are: attr_id: 2      std: accel
    attribute count 13       and values are: attr_id: 4      sint: 82179
    attribute count 14       and values are: attr_id: 13     boolean 1
    attribute count 15       and values are: attr_id: 14     boolean 0
    attribute count 16       and values are: attr_id: 18     sint: 0
    attribute count 17       and values are: attr_id: 20     flt: 0.000000  flt: 0.000000   flt: 0.000000   flt: 0.000000   flt: 0.000000   flt: 0.000000flt: 0.000000    flt: 0.000000   flt: 0.000000   flt: 0.000000   flt: 0.000000   flt: 0.000000
    attribute count 18       and values are: attr_id: 19     sint: 0
    attribute count 19       and values are: attr_id: 11
    attribute count 20       and values are: attr_id: 7      flt: 0.000019  flt: 0.000037   flt: 0.000075   flt: 0.000150   flt: 0.000299
    attribute count 21       and values are: attr_id: 24
    attribute count 22       and values are: attr_id: 23     flt: 0.000299
    attribute count 23       and values are: attr_id: 6      flt: 12.500000 flt: 25.000000  flt: 50.000000  flt: 100.000000 flt: 200.000000 flt: 500.000000
    attribute count 24       and values are: attr_id: 25     flt: 1000.000000       flt: 2000.000000
    attribute count 25       and values are: attr_id: 8      sint: 80
    attribute count 26       and values are: attr_id: 3      boolean 1
    
    Attributes for all suids received

    Streaming started
    sending request for - suid_low=6360260105974108950 suid_high=7037810611998542250
    Data request response received.
    Received re-configuration event
    Cal event packet received
    Received Samples:       [0.347159],     [-0.181959],    [9.450213],
    Received Samples:       [0.102951],     [-0.183156],    [9.545981],
    Received Samples:       [0.096965],     [-0.189142],    [9.550770],
    Received Samples:       [0.092177],     [-0.192733],    [9.541193],
    Received Samples:       [0.090980],     [-0.183156],    [9.555558],
    Received Samples:       [0.093374],     [-0.185551],    [9.555558],
    Received Samples:       [0.108936],     [-0.184354],    [9.541193],
    Received Samples:       [0.098162],     [-0.185551],    [9.565135],
    Received Samples:       [0.095768],     [-0.185551],    [9.550770],
    Received Samples:       [0.100556],     [-0.193930],    [9.550770],
    Received Samples:       [0.092177],     [-0.186748],    [9.550770],
    Received Samples:       [0.094571],     [-0.199916],    [9.541193],
    Received Samples:       [0.105345],     [-0.199916],    [9.550770],
    Received Samples:       [0.098162],     [-0.185551],    [9.550770],
    Copy to clipboard

有关常见问题的故障排除，请参阅[调试](https://docs.qualcomm.com/doc/80-70017-7SC/topic/debug.html#id1)。

关于更多信息，请参阅 [Qualcomm Linux Sensors Guide - Addendum](https://docs.qualcomm.com/bundle/resource/topics/80-70017-7A/overview.html) 中的 [Samples &gt; QSH direct channel API workflow](https://docs.qualcomm.com/bundle/resource/topics/80-70017-7A/samples.html#qsh_direct_channel_api_workflow.html)。此信息可供具有授权访问权限的许可用户使用。

## QSH 示例算法以及与 QSH 的集成

关于更多信息，请参阅 [Qualcomm Linux Sensors Guide - Addendum](https://docs.qualcomm.com/bundle/resource/topics/80-70017-7A/overview.html) 中的 [Samples &gt; QSH sample algorithm and integration with QSH](https://docs.qualcomm.com/bundle/resource/topics/80-70017-7A/samples.html#developing_custom_algorithm_and_integrating_with_qualcomm_sensing_hub.html)。此信息可供具有授权访问权限的许可用户使用。

Note

[Qualcomm Linux Sensors Guide - Addendum](https://docs.qualcomm.com/bundle/resource/topics/80-70017-7A/overview.html) 仅可由许可用户访问。

Last Published: Jan 23, 2025

[Previous Topic
软件](https://docs.qualcomm.com/bundle/publicresource/80-70017-7SC/topics/software.md) [Next Topic
工具](https://docs.qualcomm.com/bundle/publicresource/80-70017-7SC/topics/test_tools.md)