refactoring
This commit is contained in:
745
app/proxy.svg
745
app/proxy.svg
@@ -4,408 +4,455 @@
|
|||||||
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
||||||
-->
|
-->
|
||||||
<!-- Title: G Pages: 1 -->
|
<!-- Title: G Pages: 1 -->
|
||||||
<svg width="720pt" height="1360pt"
|
<svg width="927pt" height="1386pt"
|
||||||
viewBox="0.00 0.00 719.50 1360.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
viewBox="0.00 0.00 927.00 1386.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1356)">
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1382)">
|
||||||
<title>G</title>
|
<title>G</title>
|
||||||
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-1356 715.5,-1356 715.5,4 -4,4"/>
|
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-1382 923,-1382 923,4 -4,4"/>
|
||||||
<!-- A0 -->
|
<!-- A0 -->
|
||||||
<g id="node1" class="node">
|
<g id="node1" class="node">
|
||||||
<title>A0</title>
|
<title>A0</title>
|
||||||
<polygon fill="#fff8dc" stroke="#000000" points="153.6964,-1250 45.3036,-1250 45.3036,-1214 159.6964,-1214 159.6964,-1244 153.6964,-1250"/>
|
<polygon fill="#fff8dc" stroke="#000000" points="565.6964,-1354 457.3036,-1354 457.3036,-1318 571.6964,-1318 571.6964,-1348 565.6964,-1354"/>
|
||||||
<polyline fill="none" stroke="#000000" points="153.6964,-1250 153.6964,-1244 "/>
|
<polyline fill="none" stroke="#000000" points="565.6964,-1354 565.6964,-1348 "/>
|
||||||
<polyline fill="none" stroke="#000000" points="159.6964,-1244 153.6964,-1244 "/>
|
<polyline fill="none" stroke="#000000" points="571.6964,-1348 565.6964,-1348 "/>
|
||||||
<text text-anchor="middle" x="102.5" y="-1235" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">You can stick notes</text>
|
<text text-anchor="middle" x="514.5" y="-1339" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">You can stick notes</text>
|
||||||
<text text-anchor="middle" x="102.5" y="-1223" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">on diagrams too!</text>
|
<text text-anchor="middle" x="514.5" y="-1327" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">on diagrams too!</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A1 -->
|
<!-- A1 -->
|
||||||
<g id="node2" class="node">
|
<g id="node2" class="node">
|
||||||
<title>A1</title>
|
<title>A1</title>
|
||||||
<polygon fill="none" stroke="#000000" points="685.1817,-942 615.8183,-942 615.8183,-906 685.1817,-906 685.1817,-942"/>
|
<polygon fill="none" stroke="#000000" points="180.5,-820 180.5,-864 302.5,-864 302.5,-820 180.5,-820"/>
|
||||||
<text text-anchor="middle" x="650.5" y="-921" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Singleton</text>
|
<text text-anchor="start" x="231.777" y="-845" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Mqtt</text>
|
||||||
|
<text text-anchor="start" x="208.9815" y="-833" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<Singleton>></text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="180.5,-764 180.5,-820 302.5,-820 302.5,-764 180.5,-764"/>
|
||||||
|
<text text-anchor="start" x="198.9875" y="-801" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>ha_restarts</text>
|
||||||
|
<text text-anchor="start" x="206.7665" y="-789" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__client</text>
|
||||||
|
<text text-anchor="start" x="190.3735" y="-777" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__cb_MqttIsUp</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="180.5,-720 180.5,-764 302.5,-764 302.5,-720 180.5,-720"/>
|
||||||
|
<text text-anchor="start" x="203.436" y="-745" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>publish()</text>
|
||||||
|
<text text-anchor="start" x="207.6045" y="-733" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>close()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A2 -->
|
<!-- A2 -->
|
||||||
<g id="node3" class="node">
|
<g id="node3" class="node">
|
||||||
<title>A2</title>
|
<title>A2</title>
|
||||||
<polygon fill="none" stroke="#000000" points="589.5,-644 589.5,-676 711.5,-676 711.5,-644 589.5,-644"/>
|
<polygon fill="none" stroke="#000000" points="187.5,-482 187.5,-514 295.5,-514 295.5,-482 187.5,-482"/>
|
||||||
<text text-anchor="start" x="640.777" y="-657" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Mqtt</text>
|
<text text-anchor="start" x="224.5535" y="-495" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Inverter</text>
|
||||||
<polygon fill="none" stroke="#000000" points="589.5,-588 589.5,-644 711.5,-644 711.5,-588 589.5,-588"/>
|
<polygon fill="none" stroke="#000000" points="187.5,-390 187.5,-482 295.5,-482 295.5,-390 187.5,-390"/>
|
||||||
<text text-anchor="start" x="607.9875" y="-625" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>ha_restarts</text>
|
<text text-anchor="start" x="217.604" y="-463" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.db_stat</text>
|
||||||
<text text-anchor="start" x="615.7665" y="-613" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__client</text>
|
<text text-anchor="start" x="210.9405" y="-451" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.entity_prfx</text>
|
||||||
<text text-anchor="start" x="599.3735" y="-601" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__cb_MqttIsUp</text>
|
<text text-anchor="start" x="201.7755" y="-439" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.discovery_prfx</text>
|
||||||
<polygon fill="none" stroke="#000000" points="589.5,-544 589.5,-588 711.5,-588 711.5,-544 589.5,-544"/>
|
<text text-anchor="start" x="201.2115" y="-427" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.proxy_node_id</text>
|
||||||
<text text-anchor="start" x="612.436" y="-569" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>publish()</text>
|
<text text-anchor="start" x="197.3225" y="-415" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.proxy_unique_id</text>
|
||||||
<text text-anchor="start" x="616.6045" y="-557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>close()</text>
|
<text text-anchor="start" x="213.1655" y="-403" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.mqtt:Mqtt</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="187.5,-370 187.5,-390 295.5,-390 295.5,-370 187.5,-370"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A1->A2 -->
|
<!-- A1->A2 -->
|
||||||
<g id="edge1" class="edge">
|
<g id="edge3" class="edge">
|
||||||
<title>A1->A2</title>
|
<title>A1->A2</title>
|
||||||
<path fill="none" stroke="#000000" d="M650.5,-895.5395C650.5,-846.311 650.5,-744.0351 650.5,-676.2069"/>
|
<path fill="none" stroke="#000000" d="M241.5,-709.8039C241.5,-654.5754 241.5,-581.9953 241.5,-526.3277"/>
|
||||||
<polygon fill="none" stroke="#000000" points="647.0001,-895.7608 650.5,-905.7608 654.0001,-895.7608 647.0001,-895.7608"/>
|
<polygon fill="#000000" stroke="#000000" points="241.5,-719.9042 237.0001,-709.9041 241.5,-714.9042 241.5001,-709.9042 241.5001,-709.9042 241.5001,-709.9042 241.5,-714.9042 246.0001,-709.9042 241.5,-719.9042 241.5,-719.9042"/>
|
||||||
</g>
|
<polygon fill="#000000" stroke="#000000" points="241.5001,-526.0023 237.5,-520.0023 241.5,-514.0023 245.5,-520.0023 241.5001,-526.0023"/>
|
||||||
<!-- A11 -->
|
|
||||||
<g id="node12" class="node">
|
|
||||||
<title>A11</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="596.5,-348 596.5,-380 704.5,-380 704.5,-348 596.5,-348"/>
|
|
||||||
<text text-anchor="start" x="633.5535" y="-361" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Inverter</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="596.5,-256 596.5,-348 704.5,-348 704.5,-256 596.5,-256"/>
|
|
||||||
<text text-anchor="start" x="626.604" y="-329" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.db_stat</text>
|
|
||||||
<text text-anchor="start" x="619.9405" y="-317" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.entity_prfx</text>
|
|
||||||
<text text-anchor="start" x="610.7755" y="-305" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.discovery_prfx</text>
|
|
||||||
<text text-anchor="start" x="610.2115" y="-293" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.proxy_node_id</text>
|
|
||||||
<text text-anchor="start" x="606.3225" y="-281" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.proxy_unique_id</text>
|
|
||||||
<text text-anchor="start" x="622.1655" y="-269" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">cls.mqtt:Mqtt</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="596.5,-236 596.5,-256 704.5,-256 704.5,-236 596.5,-236"/>
|
|
||||||
</g>
|
|
||||||
<!-- A2->A11 -->
|
|
||||||
<g id="edge13" class="edge">
|
|
||||||
<title>A2->A11</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M650.5,-543.7248C650.5,-495.3688 650.5,-429.8734 650.5,-380.1918"/>
|
|
||||||
</g>
|
</g>
|
||||||
<!-- A3 -->
|
<!-- A3 -->
|
||||||
<g id="node4" class="node">
|
<g id="node4" class="node">
|
||||||
<title>A3</title>
|
<title>A3</title>
|
||||||
<polygon fill="none" stroke="#000000" points="318.5,-402 318.5,-434 393.5,-434 393.5,-402 318.5,-402"/>
|
<polygon fill="none" stroke="#000000" points="142.5,-186 142.5,-218 264.5,-218 264.5,-186 142.5,-186"/>
|
||||||
<text text-anchor="start" x="338.2175" y="-415" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Modbus</text>
|
<text text-anchor="start" x="179.8845" y="-199" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3</text>
|
||||||
<polygon fill="none" stroke="#000000" points="318.5,-250 318.5,-402 393.5,-402 393.5,-250 318.5,-250"/>
|
<polygon fill="none" stroke="#000000" points="142.5,-154 142.5,-186 264.5,-186 264.5,-154 142.5,-154"/>
|
||||||
<text text-anchor="start" x="347.6615" y="-383" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">que</text>
|
<text text-anchor="start" x="172.9355" y="-167" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
||||||
<text text-anchor="start" x="328.49" y="-359" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">snd_handler</text>
|
<polygon fill="none" stroke="#000000" points="142.5,-86 142.5,-154 264.5,-154 264.5,-86 142.5,-86"/>
|
||||||
<text text-anchor="start" x="329.605" y="-347" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rsp_handler</text>
|
<text text-anchor="start" x="152.1035" y="-135" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">async_create_remote()</text>
|
||||||
<text text-anchor="start" x="339.6085" y="-335" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">timeout</text>
|
<text text-anchor="start" x="162.382" y="-123" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">async_publ_mqtt()</text>
|
||||||
<text text-anchor="start" x="329.8895" y="-323" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">max_retires</text>
|
<text text-anchor="start" x="188.5025" y="-99" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
<text text-anchor="start" x="337.942" y="-311" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">last_xxx</text>
|
</g>
|
||||||
<text text-anchor="start" x="349.8915" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">err</text>
|
<!-- A2->A3 -->
|
||||||
<text text-anchor="start" x="336.5535" y="-287" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">retry_cnt</text>
|
<g id="edge1" class="edge">
|
||||||
<text text-anchor="start" x="334.879" y="-275" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">req_pend</text>
|
<title>A2->A3</title>
|
||||||
<text text-anchor="start" x="349.3365" y="-263" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tim</text>
|
<path fill="none" stroke="#000000" d="M230.7486,-359.9499C224.8735,-315.1138 217.6928,-260.3131 212.1779,-218.2258"/>
|
||||||
<polygon fill="none" stroke="#000000" points="318.5,-182 318.5,-250 393.5,-250 393.5,-182 318.5,-182"/>
|
<polygon fill="none" stroke="#000000" points="227.2883,-360.4815 232.0579,-369.942 234.2289,-359.572 227.2883,-360.4815"/>
|
||||||
<text text-anchor="start" x="329.89" y="-231" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">build_msg()</text>
|
|
||||||
<text text-anchor="start" x="333.224" y="-219" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">recv_req()</text>
|
|
||||||
<text text-anchor="start" x="330.724" y="-207" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">recv_resp()</text>
|
|
||||||
<text text-anchor="start" x="341.0025" y="-195" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
|
||||||
</g>
|
</g>
|
||||||
<!-- A4 -->
|
<!-- A4 -->
|
||||||
<g id="node5" class="node">
|
<g id="node5" class="node">
|
||||||
<title>A4</title>
|
<title>A4</title>
|
||||||
<polygon fill="none" stroke="#000000" points="308.5,-1242 308.5,-1274 379.5,-1274 379.5,-1242 308.5,-1242"/>
|
<polygon fill="none" stroke="#000000" points="528.5,-180 528.5,-212 647.5,-212 647.5,-180 528.5,-180"/>
|
||||||
<text text-anchor="start" x="318.445" y="-1255" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">IterRegistry</text>
|
<text text-anchor="start" x="561.05" y="-193" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3P</text>
|
||||||
<polygon fill="none" stroke="#000000" points="308.5,-1222 308.5,-1242 379.5,-1242 379.5,-1222 308.5,-1222"/>
|
<polygon fill="none" stroke="#000000" points="528.5,-148 528.5,-180 647.5,-180 647.5,-148 528.5,-148"/>
|
||||||
<polygon fill="none" stroke="#000000" points="308.5,-1190 308.5,-1222 379.5,-1222 379.5,-1190 308.5,-1190"/>
|
<text text-anchor="start" x="557.4355" y="-161" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
||||||
<text text-anchor="start" x="325.939" y="-1203" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__iter__</text>
|
<polygon fill="none" stroke="#000000" points="528.5,-92 528.5,-148 647.5,-148 647.5,-92 528.5,-92"/>
|
||||||
|
<text text-anchor="start" x="538.268" y="-129" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">async_create_remote(</text>
|
||||||
|
<text text-anchor="start" x="545.2175" y="-117" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">)async_publ_mqtt()</text>
|
||||||
|
<text text-anchor="start" x="573.0025" y="-105" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A2->A4 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>A2->A4</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M253.8698,-359.8546C262.7907,-327.0676 278.1312,-291.5818 304.5,-268 375.3712,-204.6196 428.113,-261.8022 512.5,-218 517.7341,-215.2832 522.9008,-212.1238 527.9257,-208.6874"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="250.3809,-359.3724 251.3023,-369.9271 257.164,-361.1015 250.3809,-359.3724"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A5 -->
|
<!-- A5 -->
|
||||||
<g id="node6" class="node">
|
<g id="node6" class="node">
|
||||||
<title>A5</title>
|
<title>A5</title>
|
||||||
<polygon fill="none" stroke="#000000" points="276.5,-1030 276.5,-1062 410.5,-1062 410.5,-1030 276.5,-1030"/>
|
<polygon fill="none" stroke="#000000" points="590.5,-1346 590.5,-1378 661.5,-1378 661.5,-1346 590.5,-1346"/>
|
||||||
<text text-anchor="start" x="323.2175" y="-1043" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Message</text>
|
<text text-anchor="start" x="600.445" y="-1359" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">IterRegistry</text>
|
||||||
<polygon fill="none" stroke="#000000" points="276.5,-854 276.5,-1030 410.5,-1030 410.5,-854 276.5,-854"/>
|
<polygon fill="none" stroke="#000000" points="590.5,-1326 590.5,-1346 661.5,-1346 661.5,-1326 590.5,-1326"/>
|
||||||
<text text-anchor="start" x="306.8265" y="-1011" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">server_side:bool</text>
|
<polygon fill="none" stroke="#000000" points="590.5,-1294 590.5,-1326 661.5,-1326 661.5,-1294 590.5,-1294"/>
|
||||||
<text text-anchor="start" x="304.043" y="-999" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">header_valid:bool</text>
|
<text text-anchor="start" x="607.939" y="-1307" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__iter__</text>
|
||||||
<text text-anchor="start" x="296.814" y="-987" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">header_len:unsigned</text>
|
|
||||||
<text text-anchor="start" x="302.648" y="-975" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">data_len:unsigned</text>
|
|
||||||
<text text-anchor="start" x="321.8245" y="-963" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">unique_id</text>
|
|
||||||
<text text-anchor="start" x="325.7135" y="-951" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">node_id</text>
|
|
||||||
<text text-anchor="start" x="322.6585" y="-939" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">sug_area</text>
|
|
||||||
<text text-anchor="start" x="293.489" y="-927" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_recv_buffer:bytearray</text>
|
|
||||||
<text text-anchor="start" x="292.0945" y="-915" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_send_buffer:bytearray</text>
|
|
||||||
<text text-anchor="start" x="286.2665" y="-903" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_forward_buffer:bytearray</text>
|
|
||||||
<text text-anchor="start" x="325.7135" y="-891" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:Infos</text>
|
|
||||||
<text text-anchor="start" x="314.326" y="-879" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">new_data:list</text>
|
|
||||||
<text text-anchor="start" x="332.662" y="-867" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">state</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="276.5,-786 276.5,-854 410.5,-854 410.5,-786 276.5,-786"/>
|
|
||||||
<text text-anchor="start" x="293.2095" y="-835" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_read():void<abstract></text>
|
|
||||||
<text text-anchor="start" x="317.9445" y="-823" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close():void</text>
|
|
||||||
<text text-anchor="start" x="303.7725" y="-811" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inc_counter():void</text>
|
|
||||||
<text text-anchor="start" x="302.1025" y="-799" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dec_counter():void</text>
|
|
||||||
</g>
|
|
||||||
<!-- A4->A5 -->
|
|
||||||
<g id="edge2" class="edge">
|
|
||||||
<title>A4->A5</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M343.5,-1179.6793C343.5,-1147.2188 343.5,-1103.8616 343.5,-1062.0836"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="340.0001,-1179.8197 343.5,-1189.8197 347.0001,-1179.8198 340.0001,-1179.8197"/>
|
|
||||||
</g>
|
</g>
|
||||||
<!-- A6 -->
|
<!-- A6 -->
|
||||||
<g id="node7" class="node">
|
<g id="node7" class="node">
|
||||||
<title>A6</title>
|
<title>A6</title>
|
||||||
<polygon fill="none" stroke="#000000" points="415.5,-704 415.5,-736 529.5,-736 529.5,-704 415.5,-704"/>
|
<polygon fill="none" stroke="#000000" points="558.5,-1212 558.5,-1244 692.5,-1244 692.5,-1212 558.5,-1212"/>
|
||||||
<text text-anchor="start" x="458.608" y="-717" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Talent</text>
|
<text text-anchor="start" x="605.2175" y="-1225" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Message</text>
|
||||||
<polygon fill="none" stroke="#000000" points="415.5,-600 415.5,-704 529.5,-704 529.5,-600 415.5,-600"/>
|
<polygon fill="none" stroke="#000000" points="558.5,-1036 558.5,-1212 692.5,-1212 692.5,-1036 558.5,-1036"/>
|
||||||
<text text-anchor="start" x="425.263" y="-685" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">await_conn_resp_cnt</text>
|
<text text-anchor="start" x="588.8265" y="-1193" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">server_side:bool</text>
|
||||||
<text text-anchor="start" x="460.2775" y="-673" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">id_str</text>
|
<text text-anchor="start" x="586.043" y="-1181" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">header_valid:bool</text>
|
||||||
<text text-anchor="start" x="441.1" y="-661" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">contact_name</text>
|
<text text-anchor="start" x="578.814" y="-1169" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">header_len:unsigned</text>
|
||||||
<text text-anchor="start" x="444.44" y="-649" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">contact_mail</text>
|
<text text-anchor="start" x="584.648" y="-1157" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">data_len:unsigned</text>
|
||||||
<text text-anchor="start" x="448.0445" y="-637" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:InfosG3</text>
|
<text text-anchor="start" x="603.8245" y="-1145" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">unique_id</text>
|
||||||
<text text-anchor="start" x="446.384" y="-625" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">mb:Modbus</text>
|
<text text-anchor="start" x="607.7135" y="-1133" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">node_id</text>
|
||||||
<text text-anchor="start" x="458.612" y="-613" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">switch</text>
|
<text text-anchor="start" x="604.6585" y="-1121" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">sug_area</text>
|
||||||
<polygon fill="none" stroke="#000000" points="415.5,-484 415.5,-600 529.5,-600 529.5,-484 415.5,-484"/>
|
<text text-anchor="start" x="575.489" y="-1109" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_recv_buffer:bytearray</text>
|
||||||
<text text-anchor="start" x="429.9925" y="-581" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_contact_info()</text>
|
<text text-anchor="start" x="574.0945" y="-1097" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_send_buffer:bytearray</text>
|
||||||
<text text-anchor="start" x="431.9325" y="-569" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_ota_update()</text>
|
<text text-anchor="start" x="568.2665" y="-1085" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_forward_buffer:bytearray</text>
|
||||||
<text text-anchor="start" x="437.7765" y="-557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_get_time()</text>
|
<text text-anchor="start" x="607.7135" y="-1073" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:Infos</text>
|
||||||
<text text-anchor="start" x="425.8285" y="-545" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_collector_data()</text>
|
<text text-anchor="start" x="596.326" y="-1061" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">new_data:list</text>
|
||||||
<text text-anchor="start" x="427.7735" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_inverter_data()</text>
|
<text text-anchor="start" x="614.662" y="-1049" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">state</text>
|
||||||
<text text-anchor="start" x="436.9405" y="-521" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_unknown()</text>
|
<polygon fill="none" stroke="#000000" points="558.5,-968 558.5,-1036 692.5,-1036 692.5,-968 558.5,-968"/>
|
||||||
<text text-anchor="start" x="457.5025" y="-497" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
<text text-anchor="start" x="575.2095" y="-1017" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_read():void<abstract></text>
|
||||||
|
<text text-anchor="start" x="599.9445" y="-1005" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close():void</text>
|
||||||
|
<text text-anchor="start" x="585.7725" y="-993" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inc_counter():void</text>
|
||||||
|
<text text-anchor="start" x="584.1025" y="-981" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dec_counter():void</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A5->A6 -->
|
<!-- A5->A6 -->
|
||||||
<g id="edge3" class="edge">
|
|
||||||
<title>A5->A6</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M404.0814,-776.5383C409.5999,-763.1056 415.1569,-749.5794 420.5898,-736.355"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="400.8317,-775.2382 400.269,-785.8181 407.3066,-777.8983 400.8317,-775.2382"/>
|
|
||||||
</g>
|
|
||||||
<!-- A7 -->
|
|
||||||
<g id="node8" class="node">
|
|
||||||
<title>A7</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="172.5,-668 172.5,-700 263.5,-700 263.5,-668 172.5,-668"/>
|
|
||||||
<text text-anchor="start" x="190.495" y="-681" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">SolarmanV5</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="172.5,-576 172.5,-668 263.5,-668 263.5,-576 172.5,-576"/>
|
|
||||||
<text text-anchor="start" x="202.998" y="-649" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">control</text>
|
|
||||||
<text text-anchor="start" x="206.0575" y="-637" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">serial</text>
|
|
||||||
<text text-anchor="start" x="211.056" y="-625" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">snr</text>
|
|
||||||
<text text-anchor="start" x="190.21" y="-613" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:InfosG3P</text>
|
|
||||||
<text text-anchor="start" x="191.884" y="-601" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">mb:Modbus</text>
|
|
||||||
<text text-anchor="start" x="204.112" y="-589" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">switch</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="172.5,-520 172.5,-576 263.5,-576 263.5,-520 172.5,-520"/>
|
|
||||||
<text text-anchor="start" x="182.4405" y="-557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_unknown()</text>
|
|
||||||
<text text-anchor="start" x="203.0025" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A5->A7 -->
|
|
||||||
<g id="edge4" class="edge">
|
<g id="edge4" class="edge">
|
||||||
<title>A5->A7</title>
|
<title>A5->A6</title>
|
||||||
<path fill="none" stroke="#000000" d="M284.228,-776.2903C273.8281,-750.3733 263.2923,-724.1174 253.7595,-700.3611"/>
|
<path fill="none" stroke="#000000" d="M625.5,-1283.5582C625.5,-1271.4749 625.5,-1258.067 625.5,-1244.189"/>
|
||||||
<polygon fill="none" stroke="#000000" points="281.0788,-777.8409 288.0512,-785.8181 287.5753,-775.2339 281.0788,-777.8409"/>
|
<polygon fill="none" stroke="#000000" points="622.0001,-1283.8144 625.5,-1293.8145 629.0001,-1283.8145 622.0001,-1283.8144"/>
|
||||||
</g>
|
|
||||||
<!-- A6->A3 -->
|
|
||||||
<g id="edge6" class="edge">
|
|
||||||
<title>A6->A3</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M420.9917,-483.781C414.3472,-467.074 407.7026,-450.1475 401.5,-434 399.8828,-429.7898 398.247,-425.4956 396.6047,-421.154"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="393.0037,-411.5882 400.7383,-419.3616 394.7652,-416.2676 396.5268,-420.947 396.5268,-420.947 396.5268,-420.947 394.7652,-416.2676 392.3154,-422.5325 393.0037,-411.5882 393.0037,-411.5882"/>
|
|
||||||
<text text-anchor="middle" x="407.3001" y="-422.5743" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
|
||||||
<text text-anchor="middle" x="406.4454" y="-467.0549" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
|
||||||
</g>
|
|
||||||
<!-- A8 -->
|
|
||||||
<g id="node9" class="node">
|
|
||||||
<title>A8</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="410.5,-330 410.5,-362 560.5,-362 560.5,-330 410.5,-330"/>
|
|
||||||
<text text-anchor="start" x="453.5455" y="-343" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ConnectionG3</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="410.5,-298 410.5,-330 560.5,-330 560.5,-298 410.5,-298"/>
|
|
||||||
<text text-anchor="start" x="420.487" y="-311" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote_stream:ConnectionG3</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="410.5,-254 410.5,-298 560.5,-298 560.5,-254 410.5,-254"/>
|
|
||||||
<text text-anchor="start" x="466.054" y="-279" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
|
||||||
<text text-anchor="start" x="470.5025" y="-267" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A6->A8 -->
|
|
||||||
<g id="edge5" class="edge">
|
|
||||||
<title>A6->A8</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M478.3685,-473.6691C480.0687,-434.1731 481.827,-393.3258 483.1723,-362.0732"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="474.8712,-473.5333 477.9378,-483.6747 481.8648,-473.8345 474.8712,-473.5333"/>
|
|
||||||
</g>
|
|
||||||
<!-- A7->A3 -->
|
|
||||||
<g id="edge8" class="edge">
|
|
||||||
<title>A7->A3</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M254.1161,-519.7083C259.8714,-507.5039 266.0613,-495.3029 272.5,-484 286.0537,-460.2067 295.6001,-458.1541 308.5,-434 310.2529,-430.7178 311.9697,-427.3559 313.6482,-423.937"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="317.9998,-414.7692 317.7769,-425.7328 315.8557,-419.2862 313.7116,-423.8032 313.7116,-423.8032 313.7116,-423.8032 315.8557,-419.2862 309.6463,-421.8735 317.9998,-414.7692 317.9998,-414.7692"/>
|
|
||||||
<text text-anchor="middle" x="317.8629" y="-431.7687" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
|
||||||
<text text-anchor="middle" x="254.262" y="-496.7088" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
|
||||||
</g>
|
|
||||||
<!-- A9 -->
|
|
||||||
<g id="node10" class="node">
|
|
||||||
<title>A9</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="125.5,-330 125.5,-362 281.5,-362 281.5,-330 125.5,-330"/>
|
|
||||||
<text text-anchor="start" x="168.211" y="-343" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ConnectionG3P</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="125.5,-298 125.5,-330 281.5,-330 281.5,-298 125.5,-298"/>
|
|
||||||
<text text-anchor="start" x="135.1525" y="-311" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote_stream:ConnectionG3P</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="125.5,-254 125.5,-298 281.5,-298 281.5,-254 125.5,-254"/>
|
|
||||||
<text text-anchor="start" x="184.054" y="-279" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
|
||||||
<text text-anchor="start" x="188.5025" y="-267" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A7->A9 -->
|
|
||||||
<g id="edge7" class="edge">
|
|
||||||
<title>A7->A9</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M212.8528,-509.7531C210.5717,-460.5471 207.9134,-403.2043 206.0152,-362.2565"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="209.3591,-509.972 213.3185,-519.7991 216.3516,-509.6477 209.3591,-509.972"/>
|
|
||||||
</g>
|
|
||||||
<!-- A8->A8 -->
|
|
||||||
<g id="edge15" class="edge">
|
|
||||||
<title>A8->A8</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M560.6684,-348.7195C571.3394,-342.1337 578.5,-328.5605 578.5,-308 578.5,-292.9008 574.6382,-281.57 568.3604,-274.0076"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="560.6684,-267.2805 571.1583,-270.4763 564.4321,-270.5721 568.1958,-273.8637 568.1958,-273.8637 568.1958,-273.8637 564.4321,-270.5721 565.2334,-277.251 560.6684,-267.2805 560.6684,-267.2805"/>
|
|
||||||
<text text-anchor="middle" x="579.877" y="-269.8507" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
|
||||||
<text text-anchor="middle" x="570.593" y="-328.3557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
|
||||||
</g>
|
|
||||||
<!-- A12 -->
|
|
||||||
<g id="node13" class="node">
|
|
||||||
<title>A12</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="506.5,-100 506.5,-132 628.5,-132 628.5,-100 506.5,-100"/>
|
|
||||||
<text text-anchor="start" x="543.8845" y="-113" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="506.5,-68 506.5,-100 628.5,-100 628.5,-68 506.5,-68"/>
|
|
||||||
<text text-anchor="start" x="536.9355" y="-81" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="506.5,0 506.5,-68 628.5,-68 628.5,0 506.5,0"/>
|
|
||||||
<text text-anchor="start" x="516.1035" y="-49" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">async_create_remote()</text>
|
|
||||||
<text text-anchor="start" x="526.382" y="-37" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">async_publ_mqtt()</text>
|
|
||||||
<text text-anchor="start" x="552.5025" y="-13" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A8->A12 -->
|
|
||||||
<g id="edge14" class="edge">
|
|
||||||
<title>A8->A12</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M507.022,-244.4839C518.719,-209.9635 533.1714,-167.3112 545.0148,-132.3588"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="503.6947,-243.3974 503.8003,-253.9917 510.3245,-245.6439 503.6947,-243.3974"/>
|
|
||||||
</g>
|
|
||||||
<!-- A9->A9 -->
|
|
||||||
<g id="edge17" class="edge">
|
|
||||||
<title>A9->A9</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M281.8471,-348.2542C292.4443,-341.506 299.5,-328.0879 299.5,-308 299.5,-293.248 295.6948,-282.093 289.4763,-274.5351"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="281.8471,-267.7458 292.3089,-271.0321 285.5822,-271.0697 289.3174,-274.3937 289.3174,-274.3937 289.3174,-274.3937 285.5822,-271.0697 286.3258,-277.7553 281.8471,-267.7458 281.8471,-267.7458"/>
|
|
||||||
<text text-anchor="middle" x="301.0069" y="-270.4817" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
|
||||||
<text text-anchor="middle" x="291.5637" y="-327.7732" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
|
||||||
</g>
|
|
||||||
<!-- A13 -->
|
|
||||||
<g id="node14" class="node">
|
|
||||||
<title>A13</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="144.5,-94 144.5,-126 263.5,-126 263.5,-94 144.5,-94"/>
|
|
||||||
<text text-anchor="start" x="177.05" y="-107" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3P</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="144.5,-62 144.5,-94 263.5,-94 263.5,-62 144.5,-62"/>
|
|
||||||
<text text-anchor="start" x="173.4355" y="-75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="144.5,-6 144.5,-62 263.5,-62 263.5,-6 144.5,-6"/>
|
|
||||||
<text text-anchor="start" x="154.268" y="-43" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">async_create_remote(</text>
|
|
||||||
<text text-anchor="start" x="161.2175" y="-31" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">)async_publ_mqtt()</text>
|
|
||||||
<text text-anchor="start" x="189.0025" y="-19" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A9->A13 -->
|
|
||||||
<g id="edge16" class="edge">
|
|
||||||
<title>A9->A13</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M203.5,-243.955C203.5,-207.4743 203.5,-162.045 203.5,-126.2187"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="200.0001,-243.9917 203.5,-253.9917 207.0001,-243.9917 200.0001,-243.9917"/>
|
|
||||||
</g>
|
|
||||||
<!-- A10 -->
|
|
||||||
<g id="node11" class="node">
|
|
||||||
<title>A10</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="281.5,-698 281.5,-730 397.5,-730 397.5,-698 281.5,-698"/>
|
|
||||||
<text text-anchor="start" x="309.774" y="-711" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStream</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="281.5,-618 281.5,-698 397.5,-698 397.5,-618 281.5,-618"/>
|
|
||||||
<text text-anchor="start" x="325.053" y="-679" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">reader</text>
|
|
||||||
<text text-anchor="start" x="327.283" y="-667" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">writer</text>
|
|
||||||
<text text-anchor="start" x="329.497" y="-655" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
|
||||||
<text text-anchor="start" x="325.053" y="-643" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">r_addr</text>
|
|
||||||
<text text-anchor="start" x="325.608" y="-631" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">l_addr</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="281.5,-490 281.5,-618 397.5,-618 397.5,-490 281.5,-490"/>
|
|
||||||
<text text-anchor="start" x="291.1575" y="-599" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>server_loop()</text>
|
|
||||||
<text text-anchor="start" x="293.378" y="-587" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>client_loop()</text>
|
|
||||||
<text text-anchor="start" x="311.154" y="-575" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>loop</text>
|
|
||||||
<text text-anchor="start" x="327.282" y="-563" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">disc()</text>
|
|
||||||
<text text-anchor="start" x="324.5025" y="-551" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
|
||||||
<text text-anchor="start" x="304.7705" y="-527" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_read()</text>
|
|
||||||
<text text-anchor="start" x="309.78" y="-515" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">async_write()</text>
|
|
||||||
<text text-anchor="start" x="298.107" y="-503" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_forward()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A10->A8 -->
|
|
||||||
<g id="edge9" class="edge">
|
|
||||||
<title>A10->A8</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M402.0319,-480.6532C422.1536,-439.0316 443.3588,-395.1687 459.3606,-362.0691"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="398.824,-479.2474 397.6226,-489.7739 405.1262,-482.2941 398.824,-479.2474"/>
|
|
||||||
</g>
|
|
||||||
<!-- A10->A9 -->
|
|
||||||
<g id="edge10" class="edge">
|
|
||||||
<title>A10->A9</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M281.2511,-480.6532C262.5076,-439.0316 242.7548,-395.1687 227.849,-362.0691"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="278.0609,-482.0929 285.3584,-489.7739 284.4435,-479.2186 278.0609,-482.0929"/>
|
|
||||||
</g>
|
|
||||||
<!-- A11->A12 -->
|
|
||||||
<g id="edge11" class="edge">
|
|
||||||
<title>A11->A12</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M622.3544,-225.9369C611.8702,-195.3687 600.1133,-161.0894 590.181,-132.1301"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="619.1547,-227.3962 625.7097,-235.7198 625.7761,-225.1252 619.1547,-227.3962"/>
|
|
||||||
</g>
|
|
||||||
<!-- A11->A13 -->
|
|
||||||
<g id="edge12" class="edge">
|
|
||||||
<title>A11->A13</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M622.0673,-226.7211C613.147,-210.1001 601.7805,-194.0346 587.5,-182 538.0407,-140.3192 358.189,-98.0533 263.2057,-77.9953"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="619.1257,-228.6587 626.7743,-235.9901 625.367,-225.4892 619.1257,-228.6587"/>
|
|
||||||
</g>
|
|
||||||
<!-- A14 -->
|
|
||||||
<g id="node15" class="node">
|
|
||||||
<title>A14</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="178.5,-1320 178.5,-1352 281.5,-1352 281.5,-1320 178.5,-1320"/>
|
|
||||||
<text text-anchor="start" x="219.162" y="-1333" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Infos</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="178.5,-1264 178.5,-1320 281.5,-1320 281.5,-1264 178.5,-1264"/>
|
|
||||||
<text text-anchor="start" x="221.9415" y="-1301" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stat</text>
|
|
||||||
<text text-anchor="start" x="197.486" y="-1289" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">new_stat_data</text>
|
|
||||||
<text text-anchor="start" x="211.1035" y="-1277" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">info_dev</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="178.5,-1112 178.5,-1264 281.5,-1264 281.5,-1112 178.5,-1112"/>
|
|
||||||
<text text-anchor="start" x="205.8355" y="-1245" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">static_init()</text>
|
|
||||||
<text text-anchor="start" x="203.8845" y="-1233" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dev_value()</text>
|
|
||||||
<text text-anchor="start" x="200.8305" y="-1221" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inc_counter()</text>
|
|
||||||
<text text-anchor="start" x="199.1605" y="-1209" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dec_counter()</text>
|
|
||||||
<text text-anchor="start" x="197.21" y="-1197" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_proxy_conf</text>
|
|
||||||
<text text-anchor="start" x="212.213" y="-1185" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_conf</text>
|
|
||||||
<text text-anchor="start" x="204.994" y="-1173" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_remove</text>
|
|
||||||
<text text-anchor="start" x="206.3745" y="-1161" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">update_db</text>
|
|
||||||
<text text-anchor="start" x="190.537" y="-1149" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">set_db_def_value</text>
|
|
||||||
<text text-anchor="start" x="199.9855" y="-1137" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">get_db_value</text>
|
|
||||||
<text text-anchor="start" x="188.3225" y="-1125" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ignore_this_device</text>
|
|
||||||
</g>
|
</g>
|
||||||
<!-- A15 -->
|
<!-- A15 -->
|
||||||
<g id="node16" class="node">
|
<g id="node16" class="node">
|
||||||
<title>A15</title>
|
<title>A15</title>
|
||||||
<polygon fill="none" stroke="#000000" points="431.5,-940 431.5,-972 498.5,-972 498.5,-940 431.5,-940"/>
|
<polygon fill="none" stroke="#000000" points="356.5,-886 356.5,-918 470.5,-918 470.5,-886 356.5,-886"/>
|
||||||
<text text-anchor="start" x="447.493" y="-953" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InfosG3</text>
|
<text text-anchor="start" x="399.608" y="-899" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Talent</text>
|
||||||
<polygon fill="none" stroke="#000000" points="431.5,-920 431.5,-940 498.5,-940 498.5,-920 431.5,-920"/>
|
<polygon fill="none" stroke="#000000" points="356.5,-782 356.5,-886 470.5,-886 470.5,-782 356.5,-782"/>
|
||||||
<polygon fill="none" stroke="#000000" points="431.5,-876 431.5,-920 498.5,-920 498.5,-876 431.5,-876"/>
|
<text text-anchor="start" x="366.263" y="-867" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">await_conn_resp_cnt</text>
|
||||||
<text text-anchor="start" x="441.384" y="-901" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_confs()</text>
|
<text text-anchor="start" x="401.2775" y="-855" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">id_str</text>
|
||||||
<text text-anchor="start" x="449.168" y="-889" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">parse()</text>
|
<text text-anchor="start" x="382.1" y="-843" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">contact_name</text>
|
||||||
|
<text text-anchor="start" x="385.44" y="-831" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">contact_mail</text>
|
||||||
|
<text text-anchor="start" x="389.0445" y="-819" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:InfosG3</text>
|
||||||
|
<text text-anchor="start" x="387.384" y="-807" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">mb:Modbus</text>
|
||||||
|
<text text-anchor="start" x="399.612" y="-795" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">switch</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="356.5,-666 356.5,-782 470.5,-782 470.5,-666 356.5,-666"/>
|
||||||
|
<text text-anchor="start" x="370.9925" y="-763" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_contact_info()</text>
|
||||||
|
<text text-anchor="start" x="372.9325" y="-751" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_ota_update()</text>
|
||||||
|
<text text-anchor="start" x="378.7765" y="-739" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_get_time()</text>
|
||||||
|
<text text-anchor="start" x="366.8285" y="-727" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_collector_data()</text>
|
||||||
|
<text text-anchor="start" x="368.7735" y="-715" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_inverter_data()</text>
|
||||||
|
<text text-anchor="start" x="377.9405" y="-703" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_unknown()</text>
|
||||||
|
<text text-anchor="start" x="398.5025" y="-679" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A14->A15 -->
|
<!-- A6->A15 -->
|
||||||
<g id="edge18" class="edge">
|
<g id="edge21" class="edge">
|
||||||
<title>A14->A15</title>
|
<title>A6->A15</title>
|
||||||
<path fill="none" stroke="#000000" d="M287.6238,-1123.7067C291.4001,-1119.5529 295.359,-1115.6229 299.5,-1112 342.985,-1073.9563 380.3024,-1104.4478 419.5,-1062 442.1524,-1037.4693 453.4109,-1001.3633 459.0018,-972.2357"/>
|
<path fill="none" stroke="#000000" d="M552.2302,-1011.4277C540.9417,-996.8789 529.4136,-982.0336 518.5,-968 501.1988,-945.7528 494.7669,-941.6895 479.5,-918 476.4901,-913.3296 473.4995,-908.5069 470.548,-903.5947"/>
|
||||||
<polygon fill="none" stroke="#000000" points="284.8741,-1121.5366 281.0238,-1131.4071 290.1891,-1126.0921 284.8741,-1121.5366"/>
|
<polygon fill="none" stroke="#000000" points="549.5765,-1013.7171 558.4715,-1019.4729 555.1073,-1009.4264 549.5765,-1013.7171"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A16 -->
|
<!-- A16 -->
|
||||||
<g id="node17" class="node">
|
<g id="node17" class="node">
|
||||||
<title>A16</title>
|
<title>A16</title>
|
||||||
<polygon fill="none" stroke="#000000" points="187.5,-940 187.5,-972 254.5,-972 254.5,-940 187.5,-940"/>
|
<polygon fill="none" stroke="#000000" points="610.5,-850 610.5,-882 701.5,-882 701.5,-850 610.5,-850"/>
|
||||||
<text text-anchor="start" x="200.1585" y="-953" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InfosG3P</text>
|
<text text-anchor="start" x="628.495" y="-863" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">SolarmanV5</text>
|
||||||
<polygon fill="none" stroke="#000000" points="187.5,-920 187.5,-940 254.5,-940 254.5,-920 187.5,-920"/>
|
<polygon fill="none" stroke="#000000" points="610.5,-758 610.5,-850 701.5,-850 701.5,-758 610.5,-758"/>
|
||||||
<polygon fill="none" stroke="#000000" points="187.5,-876 187.5,-920 254.5,-920 254.5,-876 187.5,-876"/>
|
<text text-anchor="start" x="640.998" y="-831" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">control</text>
|
||||||
<text text-anchor="start" x="197.384" y="-901" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_confs()</text>
|
<text text-anchor="start" x="644.0575" y="-819" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">serial</text>
|
||||||
<text text-anchor="start" x="205.168" y="-889" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">parse()</text>
|
<text text-anchor="start" x="649.056" y="-807" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">snr</text>
|
||||||
|
<text text-anchor="start" x="628.21" y="-795" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:InfosG3P</text>
|
||||||
|
<text text-anchor="start" x="629.884" y="-783" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">mb:Modbus</text>
|
||||||
|
<text text-anchor="start" x="642.112" y="-771" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">switch</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="610.5,-702 610.5,-758 701.5,-758 701.5,-702 610.5,-702"/>
|
||||||
|
<text text-anchor="start" x="620.4405" y="-739" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_unknown()</text>
|
||||||
|
<text text-anchor="start" x="641.0025" y="-715" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A14->A16 -->
|
<!-- A6->A16 -->
|
||||||
<g id="edge19" class="edge">
|
<g id="edge22" class="edge">
|
||||||
<title>A14->A16</title>
|
<title>A6->A16</title>
|
||||||
<path fill="none" stroke="#000000" d="M225.6878,-1101.5366C224.3454,-1055.5988 222.9195,-1006.7991 221.9029,-972.012"/>
|
<path fill="none" stroke="#000000" d="M639.6776,-957.6082C642.1325,-931.9128 644.617,-905.9091 646.8668,-882.3611"/>
|
||||||
<polygon fill="none" stroke="#000000" points="222.191,-1101.7024 225.9817,-1111.5959 229.188,-1101.4979 222.191,-1101.7024"/>
|
<polygon fill="none" stroke="#000000" points="636.1691,-957.5305 638.7021,-967.8181 643.1374,-958.1963 636.1691,-957.5305"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A15->A6 -->
|
<!-- A7 -->
|
||||||
<g id="edge21" class="edge">
|
<g id="node8" class="node">
|
||||||
<title>A15->A6</title>
|
<title>A7</title>
|
||||||
<path fill="none" stroke="#000000" d="M465.7237,-875.9684C466.6086,-841.2366 467.8512,-792.4655 469.031,-746.1572"/>
|
<polygon fill="none" stroke="#000000" points="399.5,-584 399.5,-616 516.5,-616 516.5,-584 399.5,-584"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="469.2896,-736.0098 473.5333,-746.1212 469.1622,-741.0082 469.0348,-746.0066 469.0348,-746.0066 469.0348,-746.0066 469.1622,-741.0082 464.5362,-745.8919 469.2896,-736.0098 469.2896,-736.0098"/>
|
<text text-anchor="start" x="427.429" y="-597" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<AsyncIfc>></text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="399.5,-564 399.5,-584 516.5,-584 516.5,-564 399.5,-564"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="399.5,-268 399.5,-564 516.5,-564 516.5,-268 399.5,-268"/>
|
||||||
|
<text text-anchor="start" x="427.436" y="-545" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">set_node_id()</text>
|
||||||
|
<text text-anchor="start" x="425.766" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">get_conn_no()</text>
|
||||||
|
<text text-anchor="start" x="439.6635" y="-509" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_add()</text>
|
||||||
|
<text text-anchor="start" x="437.444" y="-497" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_flush()</text>
|
||||||
|
<text text-anchor="start" x="441.0535" y="-485" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_get()</text>
|
||||||
|
<text text-anchor="start" x="437.1635" y="-473" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_peek()</text>
|
||||||
|
<text text-anchor="start" x="441.3335" y="-461" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_log()</text>
|
||||||
|
<text text-anchor="start" x="437.169" y="-449" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_clear()</text>
|
||||||
|
<text text-anchor="start" x="441.3335" y="-437" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_len()</text>
|
||||||
|
<text text-anchor="start" x="435.7745" y="-413" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">fwd_add()</text>
|
||||||
|
<text text-anchor="start" x="433.555" y="-401" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">fwd_flush()</text>
|
||||||
|
<text text-anchor="start" x="437.4445" y="-389" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">fwd_log()</text>
|
||||||
|
<text text-anchor="start" x="433.28" y="-377" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">fwd_clear()</text>
|
||||||
|
<text text-anchor="start" x="440.7785" y="-365" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_get()</text>
|
||||||
|
<text text-anchor="start" x="436.8885" y="-353" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_peek()</text>
|
||||||
|
<text text-anchor="start" x="441.0585" y="-341" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_log()</text>
|
||||||
|
<text text-anchor="start" x="436.894" y="-329" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_clear()</text>
|
||||||
|
<text text-anchor="start" x="441.0585" y="-317" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_len()</text>
|
||||||
|
<text text-anchor="start" x="432.999" y="-305" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_set_cb()</text>
|
||||||
|
<text text-anchor="start" x="409.3795" y="-281" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">prot_set_timeout_cb()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A8 -->
|
||||||
|
<g id="node9" class="node">
|
||||||
|
<title>A8</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="411.5,-182 411.5,-214 504.5,-214 504.5,-182 411.5,-182"/>
|
||||||
|
<text text-anchor="start" x="429.664" y="-195" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncIfcImpl</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="411.5,-90 411.5,-182 504.5,-182 504.5,-90 411.5,-90"/>
|
||||||
|
<text text-anchor="start" x="421.048" y="-163" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">fwd_fifo:ByteFifo</text>
|
||||||
|
<text text-anchor="start" x="424.937" y="-151" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_fifo:ByteFifo</text>
|
||||||
|
<text text-anchor="start" x="424.662" y="-139" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_fifo:ByteFifo</text>
|
||||||
|
<text text-anchor="start" x="424.096" y="-127" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">conn_no:Count</text>
|
||||||
|
<text text-anchor="start" x="440.2135" y="-115" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">node_id</text>
|
||||||
|
<text text-anchor="start" x="433.5495" y="-103" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">timeout_cb</text>
|
||||||
|
</g>
|
||||||
|
<!-- A7->A8 -->
|
||||||
|
<g id="edge5" class="edge">
|
||||||
|
<title>A7->A8</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M457.5,-257.632C457.5,-242.1873 457.5,-227.3874 457.5,-214.0086"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="454.0001,-257.8659 457.5,-267.8659 461.0001,-257.866 454.0001,-257.8659"/>
|
||||||
|
</g>
|
||||||
|
<!-- A9 -->
|
||||||
|
<g id="node10" class="node">
|
||||||
|
<title>A9</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="501.4532,-36 413.5468,-36 413.5468,0 501.4532,0 501.4532,-36"/>
|
||||||
|
<text text-anchor="middle" x="457.5" y="-15" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStream</text>
|
||||||
|
</g>
|
||||||
|
<!-- A8->A9 -->
|
||||||
|
<g id="edge6" class="edge">
|
||||||
|
<title>A8->A9</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M457.5,-79.615C457.5,-63.4386 457.5,-47.6836 457.5,-36.1546"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="457.5,-89.7075 453.0001,-79.7074 457.5,-84.7075 457.5001,-79.7075 457.5001,-79.7075 457.5001,-79.7075 457.5,-84.7075 462.0001,-79.7075 457.5,-89.7075 457.5,-89.7075"/>
|
||||||
|
</g>
|
||||||
|
<!-- A10 -->
|
||||||
|
<g id="node11" class="node">
|
||||||
|
<title>A10</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points=".5,-464 .5,-496 151.5,-496 151.5,-464 .5,-464"/>
|
||||||
|
<text text-anchor="start" x="44.0455" y="-477" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ConnectionG3</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points=".5,-432 .5,-464 151.5,-464 151.5,-432 .5,-432"/>
|
||||||
|
<text text-anchor="start" x="10.432" y="-445" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote.stream:ConnectionG3</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points=".5,-388 .5,-432 151.5,-432 151.5,-388 .5,-388"/>
|
||||||
|
<text text-anchor="start" x="56.554" y="-413" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
||||||
|
<text text-anchor="start" x="61.0025" y="-401" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A10->A3 -->
|
||||||
|
<g id="edge7" class="edge">
|
||||||
|
<title>A10->A3</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M103.5115,-378.5364C124.4716,-331.0488 153.0618,-266.2741 174.3025,-218.1506"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="100.2617,-377.2316 99.4257,-387.7934 106.6657,-380.0582 100.2617,-377.2316"/>
|
||||||
|
</g>
|
||||||
|
<!-- A10->A9 -->
|
||||||
|
<g id="edge9" class="edge">
|
||||||
|
<title>A10->A9</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M65.9191,-375.3961C58.4986,-295.6629 59.6829,-163.2447 133.5,-86 170.0095,-47.7953 321.2395,-29.3905 403.5448,-22.053"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="65.9586,-375.7857 70.5458,-381.3497 67.1741,-387.724 62.5869,-382.16 65.9586,-375.7857"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="413.7128,-21.1716 404.1388,-26.5185 408.7314,-21.6034 403.7501,-22.0353 403.7501,-22.0353 403.7501,-22.0353 408.7314,-21.6034 403.3615,-17.5521 413.7128,-21.1716 413.7128,-21.1716"/>
|
||||||
|
<text text-anchor="middle" x="396.3843" y="-28.1578" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
</g>
|
||||||
|
<!-- A10->A10 -->
|
||||||
|
<g id="edge8" class="edge">
|
||||||
|
<title>A10->A10</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M129.3063,-496.0431C150.8867,-499.0964 169,-481.082 169,-442 169,-409.3299 156.3426,-391.3816 139.5832,-388.1553"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="129.3063,-387.9569 139.3914,-383.6508 134.3054,-388.0534 139.3044,-388.15 139.3044,-388.15 139.3044,-388.15 134.3054,-388.0534 139.2175,-392.6492 129.3063,-387.9569 129.3063,-387.9569"/>
|
||||||
|
<text text-anchor="middle" x="147.5922" y="-376.856" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
||||||
|
<text text-anchor="middle" x="147.7917" y="-485.4082" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
||||||
|
</g>
|
||||||
|
<!-- A11 -->
|
||||||
|
<g id="node12" class="node">
|
||||||
|
<title>A11</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="744.5,-464 744.5,-496 901.5,-496 901.5,-464 744.5,-464"/>
|
||||||
|
<text text-anchor="start" x="787.711" y="-477" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ConnectionG3P</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="744.5,-432 744.5,-464 901.5,-464 901.5,-432 744.5,-432"/>
|
||||||
|
<text text-anchor="start" x="754.0975" y="-445" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote.stream:ConnectionG3P</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="744.5,-388 744.5,-432 901.5,-432 901.5,-388 744.5,-388"/>
|
||||||
|
<text text-anchor="start" x="803.554" y="-413" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
||||||
|
<text text-anchor="start" x="808.0025" y="-401" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A11->A4 -->
|
||||||
|
<g id="edge10" class="edge">
|
||||||
|
<title>A11->A4</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M798.6926,-378.1971C783.8063,-343.412 762.3505,-300.8772 735.5,-268 710.6165,-237.5312 676.3674,-210.0448 647.0827,-189.4838"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="795.6201,-379.9208 802.7161,-387.7883 802.0752,-377.2128 795.6201,-379.9208"/>
|
||||||
|
</g>
|
||||||
|
<!-- A11->A9 -->
|
||||||
|
<g id="edge12" class="edge">
|
||||||
|
<title>A11->A9</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M808.4328,-376.0571C788.1602,-296.5483 743.2373,-163.9158 656.5,-86 615.9314,-49.5574 554.9588,-32.4915 511.2023,-24.5972"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="808.4732,-376.2202 813.8001,-381.0807 811.3623,-387.8673 806.0354,-383.0068 808.4732,-376.2202"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="501.3083,-22.9145 511.9213,-20.1549 506.2375,-23.7529 511.1668,-24.5912 511.1668,-24.5912 511.1668,-24.5912 506.2375,-23.7529 510.4123,-29.0275 501.3083,-22.9145 501.3083,-22.9145"/>
|
||||||
|
<text text-anchor="middle" x="520.595" y="-14.6208" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
</g>
|
||||||
|
<!-- A11->A11 -->
|
||||||
|
<g id="edge11" class="edge">
|
||||||
|
<title>A11->A11</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M878.0327,-496.0431C900.3055,-499.0964 919,-481.082 919,-442 919,-409.0245 905.6911,-391.0474 888.1533,-388.0687"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="878.0327,-387.9569 888.0819,-383.5677 883.0324,-388.0122 888.0321,-388.0675 888.0321,-388.0675 888.0321,-388.0675 883.0324,-388.0122 887.9823,-392.5672 878.0327,-387.9569 878.0327,-387.9569"/>
|
||||||
|
<text text-anchor="middle" x="896.2511" y="-376.7053" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
||||||
|
<text text-anchor="middle" x="896.5075" y="-485.3826" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
||||||
|
</g>
|
||||||
|
<!-- A12 -->
|
||||||
|
<g id="node13" class="node">
|
||||||
|
<title>A12</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="489.5,-880 489.5,-912 592.5,-912 592.5,-880 489.5,-880"/>
|
||||||
|
<text text-anchor="start" x="530.162" y="-893" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Infos</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="489.5,-824 489.5,-880 592.5,-880 592.5,-824 489.5,-824"/>
|
||||||
|
<text text-anchor="start" x="532.9415" y="-861" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stat</text>
|
||||||
|
<text text-anchor="start" x="508.486" y="-849" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">new_stat_data</text>
|
||||||
|
<text text-anchor="start" x="522.1035" y="-837" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">info_dev</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="489.5,-672 489.5,-824 592.5,-824 592.5,-672 489.5,-672"/>
|
||||||
|
<text text-anchor="start" x="516.8355" y="-805" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">static_init()</text>
|
||||||
|
<text text-anchor="start" x="514.8845" y="-793" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dev_value()</text>
|
||||||
|
<text text-anchor="start" x="511.8305" y="-781" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inc_counter()</text>
|
||||||
|
<text text-anchor="start" x="510.1605" y="-769" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dec_counter()</text>
|
||||||
|
<text text-anchor="start" x="508.21" y="-757" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_proxy_conf</text>
|
||||||
|
<text text-anchor="start" x="523.213" y="-745" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_conf</text>
|
||||||
|
<text text-anchor="start" x="515.994" y="-733" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_remove</text>
|
||||||
|
<text text-anchor="start" x="517.3745" y="-721" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">update_db</text>
|
||||||
|
<text text-anchor="start" x="501.537" y="-709" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">set_db_def_value</text>
|
||||||
|
<text text-anchor="start" x="510.9855" y="-697" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">get_db_value</text>
|
||||||
|
<text text-anchor="start" x="499.3225" y="-685" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ignore_this_device</text>
|
||||||
|
</g>
|
||||||
|
<!-- A13 -->
|
||||||
|
<g id="node14" class="node">
|
||||||
|
<title>A13</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="314.5,-458 314.5,-490 381.5,-490 381.5,-458 314.5,-458"/>
|
||||||
|
<text text-anchor="start" x="330.493" y="-471" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InfosG3</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="314.5,-438 314.5,-458 381.5,-458 381.5,-438 314.5,-438"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="314.5,-394 314.5,-438 381.5,-438 381.5,-394 314.5,-394"/>
|
||||||
|
<text text-anchor="start" x="324.384" y="-419" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_confs()</text>
|
||||||
|
<text text-anchor="start" x="332.168" y="-407" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">parse()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A12->A13 -->
|
||||||
|
<g id="edge13" class="edge">
|
||||||
|
<title>A12->A13</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M482.2133,-668.9537C481.32,-667.9536 480.4156,-666.9686 479.5,-666 448.0663,-632.7472 417.2023,-652.4199 389.5,-616 361.9383,-579.7649 352.1673,-528.0191 348.8512,-490.3816"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="479.7494,-671.4639 488.8434,-676.8998 485.1241,-666.9792 479.7494,-671.4639"/>
|
||||||
|
</g>
|
||||||
|
<!-- A14 -->
|
||||||
|
<g id="node15" class="node">
|
||||||
|
<title>A14</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="659.5,-458 659.5,-490 726.5,-490 726.5,-458 659.5,-458"/>
|
||||||
|
<text text-anchor="start" x="672.1585" y="-471" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InfosG3P</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="659.5,-438 659.5,-458 726.5,-458 726.5,-438 659.5,-438"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="659.5,-394 659.5,-438 726.5,-438 726.5,-394 659.5,-394"/>
|
||||||
|
<text text-anchor="start" x="669.384" y="-419" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_confs()</text>
|
||||||
|
<text text-anchor="start" x="677.168" y="-407" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">parse()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A12->A14 -->
|
||||||
|
<g id="edge14" class="edge">
|
||||||
|
<title>A12->A14</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M597.6498,-671.6826C598.9193,-669.7598 600.2029,-667.864 601.5,-666 619.0948,-640.7144 634.6333,-642.98 649.5,-616 671.1251,-576.755 682.0274,-526.606 687.4278,-490.2373"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="594.5993,-669.9569 592.1768,-680.2711 600.5026,-673.7188 594.5993,-669.9569"/>
|
||||||
|
</g>
|
||||||
|
<!-- A15->A7 -->
|
||||||
|
<g id="edge16" class="edge">
|
||||||
|
<title>A15->A7</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M429.385,-665.642C430.9935,-652.8472 432.6494,-639.6756 434.3143,-626.4317"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="435.5886,-616.295 438.8061,-626.7783 434.9649,-621.256 434.3412,-626.217 434.3412,-626.217 434.3412,-626.217 434.9649,-621.256 429.8764,-625.6556 435.5886,-616.295 435.5886,-616.295"/>
|
||||||
|
<text text-anchor="middle" x="423.2596" y="-643.6031" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">use</text>
|
||||||
|
</g>
|
||||||
|
<!-- A15->A10 -->
|
||||||
|
<g id="edge15" class="edge">
|
||||||
|
<title>A15->A10</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M349.6312,-700.7451C337.9746,-687.9557 325.1424,-675.8414 311.5,-666 260.2851,-629.0543 226.8831,-656.5836 178.5,-616 140.443,-584.0779 112.9887,-534.285 96.0432,-496.1296"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="347.1067,-703.1737 356.3558,-708.3413 352.348,-698.5337 347.1067,-703.1737"/>
|
||||||
|
</g>
|
||||||
|
<!-- A15->A13 -->
|
||||||
|
<g id="edge17" class="edge">
|
||||||
|
<title>A15->A13</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M389.6725,-665.642C378.9966,-609.0277 366.9296,-545.0355 358.447,-500.0525"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="356.5861,-490.1839 362.8613,-499.1768 357.5127,-495.0973 358.4392,-500.0107 358.4392,-500.0107 358.4392,-500.0107 357.5127,-495.0973 354.0172,-500.8446 356.5861,-490.1839 356.5861,-490.1839"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A16->A7 -->
|
<!-- A16->A7 -->
|
||||||
<g id="edge20" class="edge">
|
<g id="edge19" class="edge">
|
||||||
<title>A16->A7</title>
|
<title>A16->A7</title>
|
||||||
<path fill="none" stroke="#000000" d="M220.0411,-875.9684C219.6216,-832.0581 218.9877,-765.7079 218.4579,-710.2644"/>
|
<path fill="none" stroke="#000000" d="M624.6836,-701.7474C618.1571,-689.0117 610.4679,-676.6496 601.5,-666 575.2168,-634.7882 550.1961,-647.697 524.5,-616 523.7865,-615.1199 523.08,-614.2314 522.3805,-613.3347"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="218.3603,-700.0467 222.9557,-710.0032 218.4081,-705.0465 218.456,-710.0463 218.456,-710.0463 218.456,-710.0463 218.4081,-705.0465 213.9562,-710.0893 218.3603,-700.0467 218.3603,-700.0467"/>
|
<polygon fill="#000000" stroke="#000000" points="516.2699,-605.0582 525.8298,-610.4303 519.2397,-609.0807 522.2095,-613.1032 522.2095,-613.1032 522.2095,-613.1032 519.2397,-609.0807 518.5893,-615.776 516.2699,-605.0582 516.2699,-605.0582"/>
|
||||||
|
<text text-anchor="middle" x="608.7901" y="-686.6067" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">use</text>
|
||||||
|
</g>
|
||||||
|
<!-- A16->A11 -->
|
||||||
|
<g id="edge18" class="edge">
|
||||||
|
<title>A16->A11</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M702.9385,-692.5781C733.3829,-628.7724 771.744,-548.3749 796.6816,-496.1104"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="699.6542,-691.3338 698.5066,-701.8663 705.9719,-694.3483 699.6542,-691.3338"/>
|
||||||
|
</g>
|
||||||
|
<!-- A16->A14 -->
|
||||||
|
<g id="edge20" class="edge">
|
||||||
|
<title>A16->A14</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M665.0284,-701.8663C671.7268,-638.5029 680.4957,-555.5538 686.3042,-500.609"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="687.389,-490.3473 690.8127,-500.765 686.8633,-495.3196 686.3376,-500.2919 686.3376,-500.2919 686.3376,-500.2919 686.8633,-495.3196 681.8626,-499.8187 687.389,-490.3473 687.389,-490.3473"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A17 -->
|
<!-- A17 -->
|
||||||
<g id="node18" class="node">
|
<g id="node18" class="node">
|
||||||
<title>A17</title>
|
<title>A17</title>
|
||||||
<polygon fill="none" stroke="#000000" points=".5,-336 .5,-368 107.5,-368 107.5,-336 .5,-336"/>
|
<polygon fill="none" stroke="#000000" points="435.5,-1200 435.5,-1232 510.5,-1232 510.5,-1200 435.5,-1200"/>
|
||||||
<text text-anchor="start" x="24.2695" y="-349" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ModbusConn</text>
|
<text text-anchor="start" x="455.2175" y="-1213" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Modbus</text>
|
||||||
<polygon fill="none" stroke="#000000" points=".5,-268 .5,-336 107.5,-336 107.5,-268 .5,-268"/>
|
<polygon fill="none" stroke="#000000" points="435.5,-1048 435.5,-1200 510.5,-1200 510.5,-1048 435.5,-1048"/>
|
||||||
<text text-anchor="start" x="44.5515" y="-317" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">host</text>
|
<text text-anchor="start" x="464.6615" y="-1181" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">que</text>
|
||||||
<text text-anchor="start" x="45.387" y="-305" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">port</text>
|
<text text-anchor="start" x="445.49" y="-1157" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">snd_handler</text>
|
||||||
<text text-anchor="start" x="43.997" y="-293" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
<text text-anchor="start" x="446.605" y="-1145" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rsp_handler</text>
|
||||||
<text text-anchor="start" x="10.383" y="-281" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stream:InverterG3P</text>
|
<text text-anchor="start" x="456.6085" y="-1133" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">timeout</text>
|
||||||
<polygon fill="none" stroke="#000000" points=".5,-248 .5,-268 107.5,-268 107.5,-248 .5,-248"/>
|
<text text-anchor="start" x="446.8895" y="-1121" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">max_retires</text>
|
||||||
|
<text text-anchor="start" x="454.942" y="-1109" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">last_xxx</text>
|
||||||
|
<text text-anchor="start" x="466.8915" y="-1097" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">err</text>
|
||||||
|
<text text-anchor="start" x="453.5535" y="-1085" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">retry_cnt</text>
|
||||||
|
<text text-anchor="start" x="451.879" y="-1073" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">req_pend</text>
|
||||||
|
<text text-anchor="start" x="466.3365" y="-1061" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tim</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="435.5,-980 435.5,-1048 510.5,-1048 510.5,-980 435.5,-980"/>
|
||||||
|
<text text-anchor="start" x="446.89" y="-1029" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">build_msg()</text>
|
||||||
|
<text text-anchor="start" x="450.224" y="-1017" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">recv_req()</text>
|
||||||
|
<text text-anchor="start" x="447.724" y="-1005" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">recv_resp()</text>
|
||||||
|
<text text-anchor="start" x="458.0025" y="-993" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A17->A13 -->
|
<!-- A17->A15 -->
|
||||||
<g id="edge22" class="edge">
|
<g id="edge24" class="edge">
|
||||||
<title>A17->A13</title>
|
<title>A17->A15</title>
|
||||||
<path fill="none" stroke="#000000" d="M80.8473,-247.8342C91.2165,-226.5814 103.6422,-202.8044 116.5,-182 126.2708,-166.1905 137.6417,-149.852 148.8772,-134.6044"/>
|
<path fill="none" stroke="#000000" d="M446.8724,-969.6092C443.6566,-952.4944 440.3783,-935.047 437.1939,-918.0999"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="155.0942,-126.2561 152.7306,-136.9642 152.1078,-130.2663 149.1214,-134.2765 149.1214,-134.2765 149.1214,-134.2765 152.1078,-130.2663 145.5123,-131.5887 155.0942,-126.2561 155.0942,-126.2561"/>
|
<polygon fill="#000000" stroke="#000000" points="448.7575,-979.6415 442.4881,-970.6445 447.8341,-974.7275 446.9107,-969.8135 446.9107,-969.8135 446.9107,-969.8135 447.8341,-974.7275 451.3333,-968.9824 448.7575,-979.6415 448.7575,-979.6415"/>
|
||||||
<text text-anchor="middle" x="151.047" y="-142.8423" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
<text text-anchor="middle" x="448.8482" y="-931.3534" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
||||||
<text text-anchor="middle" x="81.2636" y="-224.8385" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
<text text-anchor="middle" x="437.1032" y="-960.3879" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
</g>
|
||||||
|
<!-- A17->A16 -->
|
||||||
|
<g id="edge23" class="edge">
|
||||||
|
<title>A17->A16</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M514.9768,-1020.5466C525.3303,-1002.5556 537.0447,-984.1492 549.5,-968 569.0808,-942.6121 583.2659,-944.3717 601.5,-918 609.1473,-906.9397 616.0494,-894.6241 622.1627,-882.146"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="510.0062,-1029.3335 511.0131,-1018.414 512.4681,-1024.9816 514.9299,-1020.6296 514.9299,-1020.6296 514.9299,-1020.6296 512.4681,-1024.9816 518.8467,-1022.8453 510.0062,-1029.3335 510.0062,-1029.3335"/>
|
||||||
|
<text text-anchor="middle" x="621.6642" y="-899.1398" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
||||||
|
<text text-anchor="middle" x="511.574" y="-1006.3951" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
</g>
|
||||||
|
<!-- A18 -->
|
||||||
|
<g id="node19" class="node">
|
||||||
|
<title>A18</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="534.5,-470 534.5,-502 641.5,-502 641.5,-470 534.5,-470"/>
|
||||||
|
<text text-anchor="start" x="558.2695" y="-483" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ModbusConn</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="534.5,-402 534.5,-470 641.5,-470 641.5,-402 534.5,-402"/>
|
||||||
|
<text text-anchor="start" x="578.5515" y="-451" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">host</text>
|
||||||
|
<text text-anchor="start" x="579.387" y="-439" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">port</text>
|
||||||
|
<text text-anchor="start" x="577.997" y="-427" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
||||||
|
<text text-anchor="start" x="544.383" y="-415" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stream:InverterG3P</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="534.5,-382 534.5,-402 641.5,-402 641.5,-382 534.5,-382"/>
|
||||||
|
</g>
|
||||||
|
<!-- A18->A4 -->
|
||||||
|
<g id="edge25" class="edge">
|
||||||
|
<title>A18->A4</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M587.5,-381.9118C587.5,-335.4458 587.5,-271.0175 587.5,-222.1832"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="587.5,-212.0112 592.0001,-222.0112 587.5,-217.0112 587.5001,-222.0112 587.5001,-222.0112 587.5001,-222.0112 587.5,-217.0112 583.0001,-222.0113 587.5,-212.0112 587.5,-212.0112"/>
|
||||||
|
<text text-anchor="middle" x="595.9524" y="-227.1374" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
<text text-anchor="middle" x="579.0476" y="-360.7857" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 39 KiB |
@@ -3,28 +3,49 @@
|
|||||||
// {generate:true}
|
// {generate:true}
|
||||||
|
|
||||||
[note: You can stick notes on diagrams too!{bg:cornsilk}]
|
[note: You can stick notes on diagrams too!{bg:cornsilk}]
|
||||||
[Singleton]^[Mqtt|<static>ha_restarts;<static>__client;<static>__cb_MqttIsUp|<async>publish();<async>close()]
|
|
||||||
[Modbus|que;;snd_handler;rsp_handler;timeout;max_retires;last_xxx;err;retry_cnt;req_pend;tim|build_msg();recv_req();recv_resp();close()]
|
[Mqtt;<<Singleton>>|<static>ha_restarts;<static>__client;<static>__cb_MqttIsUp|<async>publish();<async>close()]
|
||||||
[IterRegistry||__iter__]^[Message|server_side:bool;header_valid:bool;header_len:unsigned;data_len:unsigned;unique_id;node_id;sug_area;_recv_buffer:bytearray;_send_buffer:bytearray;_forward_buffer:bytearray;db:Infos;new_data:list;state|_read():void<abstract>;close():void;inc_counter():void;dec_counter():void]
|
[Inverter|cls.db_stat;cls.entity_prfx;cls.discovery_prfx;cls.proxy_node_id;cls.proxy_unique_id;cls.mqtt:Mqtt|]
|
||||||
[Message]^[Talent|await_conn_resp_cnt;id_str;contact_name;contact_mail;db:InfosG3;mb:Modbus;switch|msg_contact_info();msg_ota_update();msg_get_time();msg_collector_data();msg_inverter_data();msg_unknown();;close()]
|
[Inverter]^[InverterG3|__ha_restarts|async_create_remote();async_publ_mqtt();;close()]
|
||||||
[Message]^[SolarmanV5|control;serial;snr;db:InfosG3P;mb:Modbus;switch|msg_unknown();;close()]
|
|
||||||
[Talent]^[ConnectionG3|remote_stream:ConnectionG3|healthy();close()]
|
|
||||||
[Talent]has-1>[Modbus]
|
|
||||||
[SolarmanV5]^[ConnectionG3P|remote_stream:ConnectionG3P|healthy();close()]
|
|
||||||
[SolarmanV5]has-1>[Modbus]
|
|
||||||
[AsyncStream|reader;writer;addr;r_addr;l_addr|<async>server_loop();<async>client_loop();<async>loop;disc();close();;__async_read();async_write();__async_forward()]^[ConnectionG3]
|
|
||||||
[AsyncStream]^[ConnectionG3P]
|
|
||||||
[Inverter|cls.db_stat;cls.entity_prfx;cls.discovery_prfx;cls.proxy_node_id;cls.proxy_unique_id;cls.mqtt:Mqtt|]^[InverterG3|__ha_restarts|async_create_remote();async_publ_mqtt();;close()]
|
|
||||||
[Inverter]^[InverterG3P|__ha_restarts|async_create_remote(;)async_publ_mqtt();close()]
|
[Inverter]^[InverterG3P|__ha_restarts|async_create_remote(;)async_publ_mqtt();close()]
|
||||||
[Mqtt]-[Inverter]
|
[Mqtt;<<Singleton>>]<-++[Inverter]
|
||||||
|
|
||||||
|
[IterRegistry||__iter__]^[Message|server_side:bool;header_valid:bool;header_len:unsigned;data_len:unsigned;unique_id;node_id;sug_area;_recv_buffer:bytearray;_send_buffer:bytearray;_forward_buffer:bytearray;db:Infos;new_data:list;state|_read():void<abstract>;close():void;inc_counter():void;dec_counter():void]
|
||||||
|
|
||||||
|
[<<AsyncIfc>>||set_node_id();get_conn_no();;tx_add();tx_flush();tx_get();tx_peek();tx_log();tx_clear();tx_len();;fwd_add();fwd_flush();fwd_log();fwd_clear();rx_get();rx_peek();rx_log();rx_clear();rx_len();rx_set_cb();;prot_set_timeout_cb()]
|
||||||
|
[AsyncIfcImpl|fwd_fifo:ByteFifo;tx_fifo:ByteFifo;rx_fifo:ByteFifo;conn_no:Count;node_id;timeout_cb]
|
||||||
|
[<<AsyncIfc>>]^-.-[AsyncIfcImpl]
|
||||||
|
[AsyncIfcImpl]<-[AsyncStream]
|
||||||
|
[AsyncStream|reader;writer;addr;r_addr;l_addr|<async>server_loop();<async>client_loop();<async>loop;disc();close();;__async_read();async_write();__async_forward()]
|
||||||
|
|
||||||
|
[ConnectionG3|remote.stream:ConnectionG3|healthy();close()]
|
||||||
[ConnectionG3]^[InverterG3]
|
[ConnectionG3]^[InverterG3]
|
||||||
[ConnectionG3]has-0..1>[ConnectionG3]
|
[ConnectionG3]has-0..1>[ConnectionG3]
|
||||||
|
[ConnectionG3]++-1>[AsyncStream]
|
||||||
|
[ConnectionG3P|remote.stream:ConnectionG3P|healthy();close()]
|
||||||
[ConnectionG3P]^[InverterG3P]
|
[ConnectionG3P]^[InverterG3P]
|
||||||
[ConnectionG3P]has-0..1>[ConnectionG3P]
|
[ConnectionG3P]has-0..1>[ConnectionG3P]
|
||||||
|
[ConnectionG3P]++-1>[AsyncStream]
|
||||||
|
|
||||||
[Infos|stat;new_stat_data;info_dev|static_init();dev_value();inc_counter();dec_counter();ha_proxy_conf;ha_conf;ha_remove;update_db;set_db_def_value;get_db_value;ignore_this_device]^[InfosG3||ha_confs();parse()]
|
[Infos|stat;new_stat_data;info_dev|static_init();dev_value();inc_counter();dec_counter();ha_proxy_conf;ha_conf;ha_remove;update_db;set_db_def_value;get_db_value;ignore_this_device]
|
||||||
|
[Infos]^[InfosG3||ha_confs();parse()]
|
||||||
[Infos]^[InfosG3P||ha_confs();parse()]
|
[Infos]^[InfosG3P||ha_confs();parse()]
|
||||||
[InfosG3P]->[SolarmanV5]
|
|
||||||
[InfosG3]->[Talent]
|
[Talent|await_conn_resp_cnt;id_str;contact_name;contact_mail;db:InfosG3;mb:Modbus;switch|msg_contact_info();msg_ota_update();msg_get_time();msg_collector_data();msg_inverter_data();msg_unknown();;close()]
|
||||||
|
[Talent]^[ConnectionG3]
|
||||||
|
[Talent]use->[<<AsyncIfc>>]
|
||||||
|
[Talent]->[InfosG3]
|
||||||
|
[SolarmanV5|control;serial;snr;db:InfosG3P;mb:Modbus;switch|msg_unknown();;close()]
|
||||||
|
[SolarmanV5]^[ConnectionG3P]
|
||||||
|
[SolarmanV5]use->[<<AsyncIfc>>]
|
||||||
|
[SolarmanV5]->[InfosG3P]
|
||||||
|
|
||||||
|
[Message]^[Talent]
|
||||||
|
[Message]^[SolarmanV5]
|
||||||
|
|
||||||
|
[Modbus|que;;snd_handler;rsp_handler;timeout;max_retires;last_xxx;err;retry_cnt;req_pend;tim|build_msg();recv_req();recv_resp();close()]
|
||||||
|
[Modbus]<1-has[SolarmanV5]
|
||||||
|
[Modbus]<1-has[Talent]
|
||||||
|
|
||||||
[ModbusConn|host;port;addr;stream:InverterG3P;|]has-1>[InverterG3P]
|
[ModbusConn|host;port;addr;stream:InverterG3P;|]has-1>[InverterG3P]
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,111 @@
|
|||||||
if __name__ == "app.src.async_ifc":
|
from abc import ABC, abstractmethod
|
||||||
from app.src.byte_fifo import ByteFifo
|
|
||||||
else: # pragma: no cover
|
|
||||||
from byte_fifo import ByteFifo
|
|
||||||
|
|
||||||
|
|
||||||
class AsyncIfc():
|
class AsyncIfc(ABC):
|
||||||
def __init__(self):
|
@abstractmethod
|
||||||
self.read = ByteFifo()
|
def get_conn_no(self):
|
||||||
self.write = ByteFifo()
|
pass # pragma: no cover
|
||||||
self.forward = ByteFifo()
|
|
||||||
|
@abstractmethod
|
||||||
|
def set_node_id(self, value: str):
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
#
|
||||||
|
# TX - QUEUE
|
||||||
|
#
|
||||||
|
@abstractmethod
|
||||||
|
def tx_add(self, data: bytearray):
|
||||||
|
''' add data to transmit queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def tx_flush(self):
|
||||||
|
''' send transmit queue and clears it'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def tx_get(self, size: int = None) -> bytearray:
|
||||||
|
'''removes size numbers of bytes and return them'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def tx_peek(self, size: int = None) -> bytearray:
|
||||||
|
'''returns size numbers of byte without removing them'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def tx_log(self, level, info):
|
||||||
|
''' log the transmit queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def tx_clear(self):
|
||||||
|
''' clear transmit queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def tx_len(self):
|
||||||
|
''' get numner of bytes in the transmit queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
#
|
||||||
|
# FORWARD - QUEUE
|
||||||
|
#
|
||||||
|
@abstractmethod
|
||||||
|
def fwd_add(self, data: bytearray):
|
||||||
|
''' add data to forward queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def fwd_flush(self):
|
||||||
|
''' send forward queue and clears it'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def fwd_log(self, level, info):
|
||||||
|
''' log the forward queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def fwd_clear(self):
|
||||||
|
''' clear forward queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
#
|
||||||
|
# RX - QUEUE
|
||||||
|
#
|
||||||
|
@abstractmethod
|
||||||
|
def rx_get(self, size: int = None) -> bytearray:
|
||||||
|
'''removes size numbers of bytes and return them'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def rx_peek(self, size: int = None) -> bytearray:
|
||||||
|
'''returns size numbers of byte without removing them'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def rx_log(self, level, info):
|
||||||
|
''' logs the receive queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def rx_clear(self):
|
||||||
|
''' clear receive queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def rx_len(self):
|
||||||
|
''' get numner of bytes in the receive queue'''
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def rx_set_cb(self, callback):
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
#
|
||||||
|
# Protocol Callbacks
|
||||||
|
#
|
||||||
|
@abstractmethod
|
||||||
|
def prot_set_timeout_cb(self, callback):
|
||||||
|
pass # pragma: no cover
|
||||||
|
|||||||
@@ -7,19 +7,114 @@ from typing import Self
|
|||||||
from itertools import count
|
from itertools import count
|
||||||
|
|
||||||
if __name__ == "app.src.async_stream":
|
if __name__ == "app.src.async_stream":
|
||||||
|
from app.src.byte_fifo import ByteFifo
|
||||||
from app.src.async_ifc import AsyncIfc
|
from app.src.async_ifc import AsyncIfc
|
||||||
from app.src.messages import State
|
from app.src.infos import Infos
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
|
from byte_fifo import ByteFifo
|
||||||
from async_ifc import AsyncIfc
|
from async_ifc import AsyncIfc
|
||||||
from messages import State
|
from infos import Infos
|
||||||
|
|
||||||
|
|
||||||
import gc
|
import gc
|
||||||
logger = logging.getLogger('conn')
|
logger = logging.getLogger('conn')
|
||||||
|
|
||||||
|
|
||||||
class AsyncStream():
|
class AsyncIfcImpl(AsyncIfc):
|
||||||
_ids = count(0)
|
_ids = count(0)
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
logger.debug('AsyncIfcImpl.__init__')
|
||||||
|
self.fwd_fifo = ByteFifo()
|
||||||
|
self.tx_fifo = ByteFifo()
|
||||||
|
self.rx_fifo = ByteFifo()
|
||||||
|
self.conn_no = next(self._ids)
|
||||||
|
self.node_id = ''
|
||||||
|
self.timeout_cb = None
|
||||||
|
|
||||||
|
def set_node_id(self, value: str):
|
||||||
|
self.node_id = value
|
||||||
|
|
||||||
|
def get_conn_no(self):
|
||||||
|
return self.conn_no
|
||||||
|
|
||||||
|
def tx_add(self, data: bytearray):
|
||||||
|
''' add data to transmit queue'''
|
||||||
|
self.tx_fifo += data
|
||||||
|
|
||||||
|
def tx_flush(self):
|
||||||
|
''' send transmit queue and clears it'''
|
||||||
|
self.tx_fifo()
|
||||||
|
|
||||||
|
def tx_get(self, size: int = None) -> bytearray:
|
||||||
|
'''removes size numbers of bytes and return them'''
|
||||||
|
return self.tx_fifo.get(size)
|
||||||
|
|
||||||
|
def tx_peek(self, size: int = None) -> bytearray:
|
||||||
|
'''returns size numbers of byte without removing them'''
|
||||||
|
return self.tx_fifo.peek(size)
|
||||||
|
|
||||||
|
def tx_log(self, level, info):
|
||||||
|
''' log the transmit queue'''
|
||||||
|
self.tx_fifo.logging(level, info)
|
||||||
|
|
||||||
|
def tx_clear(self):
|
||||||
|
''' clear transmit queue'''
|
||||||
|
self.tx_fifo.clear()
|
||||||
|
|
||||||
|
def tx_len(self):
|
||||||
|
''' get numner of bytes in the transmit queue'''
|
||||||
|
return len(self.tx_fifo)
|
||||||
|
|
||||||
|
def fwd_add(self, data: bytearray):
|
||||||
|
''' add data to forward queue'''
|
||||||
|
self.fwd_fifo += data
|
||||||
|
|
||||||
|
def fwd_flush(self):
|
||||||
|
''' send forward queue and clears it'''
|
||||||
|
self.fwd_fifo()
|
||||||
|
|
||||||
|
def fwd_log(self, level, info):
|
||||||
|
''' log the forward queue'''
|
||||||
|
self.fwd_fifo.logging(level, info)
|
||||||
|
|
||||||
|
def fwd_clear(self):
|
||||||
|
''' clear forward queue'''
|
||||||
|
self.fwd_fifo.clear()
|
||||||
|
|
||||||
|
def rx_get(self, size: int = None) -> bytearray:
|
||||||
|
'''removes size numbers of bytes and return them'''
|
||||||
|
return self.rx_fifo.get(size)
|
||||||
|
|
||||||
|
def rx_peek(self, size: int = None) -> bytearray:
|
||||||
|
'''returns size numbers of byte without removing them'''
|
||||||
|
return self.rx_fifo.peek(size)
|
||||||
|
|
||||||
|
def rx_log(self, level, info):
|
||||||
|
''' logs the receive queue'''
|
||||||
|
self.rx_fifo.logging(level, info)
|
||||||
|
|
||||||
|
def rx_clear(self):
|
||||||
|
''' clear receive queue'''
|
||||||
|
self.rx_fifo.clear()
|
||||||
|
|
||||||
|
def rx_len(self):
|
||||||
|
''' get numner of bytes in the receive queue'''
|
||||||
|
return len(self.rx_fifo)
|
||||||
|
|
||||||
|
def rx_set_cb(self, callback):
|
||||||
|
self.rx_fifo.reg_trigger(callback)
|
||||||
|
|
||||||
|
def prot_set_timeout_cb(self, callback):
|
||||||
|
self.timeout_cb = callback
|
||||||
|
|
||||||
|
|
||||||
|
class StreamPtr():
|
||||||
|
def __init__(self, stream):
|
||||||
|
self.stream = stream
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncStream(AsyncIfcImpl):
|
||||||
MAX_PROC_TIME = 2
|
MAX_PROC_TIME = 2
|
||||||
'''maximum processing time for a received msg in sec'''
|
'''maximum processing time for a received msg in sec'''
|
||||||
MAX_START_TIME = 400
|
MAX_START_TIME = 400
|
||||||
@@ -30,31 +125,31 @@ class AsyncStream():
|
|||||||
'''maximum default time without a received msg in sec'''
|
'''maximum default time without a received msg in sec'''
|
||||||
|
|
||||||
def __init__(self, reader: StreamReader, writer: StreamWriter,
|
def __init__(self, reader: StreamReader, writer: StreamWriter,
|
||||||
addr, ifc: "AsyncIfc") -> None:
|
addr, async_publ_mqtt, async_create_remote,
|
||||||
|
rstream: "StreamPtr") -> None:
|
||||||
|
AsyncIfcImpl.__init__(self)
|
||||||
|
|
||||||
logger.debug('AsyncStream.__init__')
|
logger.debug('AsyncStream.__init__')
|
||||||
ifc.write.reg_trigger(self.__write_cb)
|
|
||||||
self.ifc = ifc
|
self.remote = rstream
|
||||||
|
self.tx_fifo.reg_trigger(self.__write_cb)
|
||||||
|
self.async_create_remote = async_create_remote
|
||||||
self._reader = reader
|
self._reader = reader
|
||||||
self._writer = writer
|
self._writer = writer
|
||||||
self.addr = addr
|
self.addr = addr
|
||||||
self.r_addr = ''
|
self.r_addr = ''
|
||||||
self.l_addr = ''
|
self.l_addr = ''
|
||||||
self.conn_no = next(self._ids)
|
|
||||||
self.proc_start = None # start processing start timestamp
|
self.proc_start = None # start processing start timestamp
|
||||||
self.proc_max = 0
|
self.proc_max = 0
|
||||||
|
self.async_publ_mqtt = async_publ_mqtt
|
||||||
|
|
||||||
def __write_cb(self):
|
def __write_cb(self):
|
||||||
self._writer.write(self.ifc.write.get())
|
self._writer.write(self.tx_fifo.get())
|
||||||
|
|
||||||
def __timeout(self) -> int:
|
def __timeout(self) -> int:
|
||||||
if self.state == State.init or self.state == State.received:
|
if self.timeout_cb is callable:
|
||||||
to = self.MAX_START_TIME
|
return self.timeout_cb
|
||||||
elif self.state == State.up and \
|
return 360
|
||||||
self.server_side and self.modbus_polling:
|
|
||||||
to = self.MAX_INV_IDLE_TIME
|
|
||||||
else:
|
|
||||||
to = self.MAX_DEF_IDLE_TIME
|
|
||||||
return to
|
|
||||||
|
|
||||||
async def publish_outstanding_mqtt(self):
|
async def publish_outstanding_mqtt(self):
|
||||||
'''Publish all outstanding MQTT topics'''
|
'''Publish all outstanding MQTT topics'''
|
||||||
@@ -69,25 +164,25 @@ class AsyncStream():
|
|||||||
'''Loop for receiving messages from the inverter (server-side)'''
|
'''Loop for receiving messages from the inverter (server-side)'''
|
||||||
logger.info(f'[{self.node_id}:{self.conn_no}] '
|
logger.info(f'[{self.node_id}:{self.conn_no}] '
|
||||||
f'Accept connection from {addr}')
|
f'Accept connection from {addr}')
|
||||||
self.inc_counter('Inverter_Cnt')
|
Infos.inc_counter('Inverter_Cnt')
|
||||||
await self.publish_outstanding_mqtt()
|
await self.publish_outstanding_mqtt()
|
||||||
await self.loop()
|
await self.loop()
|
||||||
self.dec_counter('Inverter_Cnt')
|
Infos.dec_counter('Inverter_Cnt')
|
||||||
await self.publish_outstanding_mqtt()
|
await self.publish_outstanding_mqtt()
|
||||||
logger.info(f'[{self.node_id}:{self.conn_no}] Server loop stopped for'
|
logger.info(f'[{self.node_id}:{self.conn_no}] Server loop stopped for'
|
||||||
f' r{self.r_addr}')
|
f' r{self.r_addr}')
|
||||||
|
|
||||||
# if the server connection closes, we also have to disconnect
|
# if the server connection closes, we also have to disconnect
|
||||||
# the connection to te TSUN cloud
|
# the connection to te TSUN cloud
|
||||||
if self.remote_stream:
|
if self.remote.stream:
|
||||||
logger.info(f'[{self.node_id}:{self.conn_no}] disc client '
|
logger.info(f'[{self.node_id}:{self.conn_no}] disc client '
|
||||||
f'connection: [{self.remote_stream.node_id}:'
|
f'connection: [{self.remote.stream.node_id}:'
|
||||||
f'{self.remote_stream.conn_no}]')
|
f'{self.remote.stream.conn_no}]')
|
||||||
await self.remote_stream.disc()
|
await self.remote.stream._ifc.disc()
|
||||||
|
|
||||||
async def client_loop(self, _: str) -> None:
|
async def client_loop(self, _: str) -> None:
|
||||||
'''Loop for receiving messages from the TSUN cloud (client-side)'''
|
'''Loop for receiving messages from the TSUN cloud (client-side)'''
|
||||||
client_stream = await self.remote_stream.loop()
|
client_stream = await self.remote.stream._ifc.loop()
|
||||||
logger.info(f'[{client_stream.node_id}:{client_stream.conn_no}] '
|
logger.info(f'[{client_stream.node_id}:{client_stream.conn_no}] '
|
||||||
'Client loop stopped for'
|
'Client loop stopped for'
|
||||||
f' l{client_stream.l_addr}')
|
f' l{client_stream.l_addr}')
|
||||||
@@ -98,13 +193,13 @@ class AsyncStream():
|
|||||||
# establish a new connection to the TSUN cloud
|
# establish a new connection to the TSUN cloud
|
||||||
|
|
||||||
# erase backlink to inverter
|
# erase backlink to inverter
|
||||||
client_stream.remote_stream = None
|
client_stream.remote.stream = None
|
||||||
|
|
||||||
if self.remote_stream == client_stream:
|
if self.remote.stream == client_stream:
|
||||||
# logging.debug(f'Client l{client_stream.l_addr} refs:'
|
# logging.debug(f'Client l{client_stream.l_addr} refs:'
|
||||||
# f' {gc.get_referrers(client_stream)}')
|
# f' {gc.get_referrers(client_stream)}')
|
||||||
# than erase client connection
|
# than erase client connection
|
||||||
self.remote_stream = None
|
self.remote.stream = None
|
||||||
|
|
||||||
async def loop(self) -> Self:
|
async def loop(self) -> Self:
|
||||||
"""Async loop handler for precessing all received messages"""
|
"""Async loop handler for precessing all received messages"""
|
||||||
@@ -121,10 +216,10 @@ class AsyncStream():
|
|||||||
await asyncio.wait_for(self.__async_read(),
|
await asyncio.wait_for(self.__async_read(),
|
||||||
dead_conn_to)
|
dead_conn_to)
|
||||||
|
|
||||||
if self.unique_id:
|
# if self.unique_id:
|
||||||
await self.__async_write()
|
await self.__async_write()
|
||||||
await self.__async_forward()
|
await self.__async_forward()
|
||||||
await self.async_publ_mqtt()
|
await self.async_publ_mqtt()
|
||||||
|
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
logger.warning(f'[{self.node_id}:{self.conn_no}] Dead '
|
logger.warning(f'[{self.node_id}:{self.conn_no}] Dead '
|
||||||
@@ -150,7 +245,7 @@ class AsyncStream():
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
self.inc_counter('SW_Exception')
|
Infos.inc_counter('SW_Exception')
|
||||||
logger.error(
|
logger.error(
|
||||||
f"Exception for {self.addr}:\n"
|
f"Exception for {self.addr}:\n"
|
||||||
f"{traceback.format_exc()}")
|
f"{traceback.format_exc()}")
|
||||||
@@ -158,9 +253,9 @@ class AsyncStream():
|
|||||||
|
|
||||||
async def __async_write(self, headline: str = 'Transmit to ') -> None:
|
async def __async_write(self, headline: str = 'Transmit to ') -> None:
|
||||||
"""Async write handler to transmit the send_buffer"""
|
"""Async write handler to transmit the send_buffer"""
|
||||||
if len(self.ifc.write) > 0:
|
if len(self.tx_fifo) > 0:
|
||||||
self.ifc.write.logging(logging.INFO, f'{headline}{self.addr}:')
|
self.tx_fifo.logging(logging.INFO, f'{headline}{self.addr}:')
|
||||||
self._writer.write(self.ifc.write.get())
|
self._writer.write(self.tx_fifo.get())
|
||||||
await self._writer.drain()
|
await self._writer.drain()
|
||||||
|
|
||||||
async def disc(self) -> None:
|
async def disc(self) -> None:
|
||||||
@@ -176,18 +271,19 @@ class AsyncStream():
|
|||||||
|
|
||||||
hint: must be called before releasing the connection instance
|
hint: must be called before releasing the connection instance
|
||||||
"""
|
"""
|
||||||
|
self.tx_fifo.reg_trigger(None)
|
||||||
|
self.async_create_remote = None
|
||||||
self._reader.feed_eof() # abort awaited read
|
self._reader.feed_eof() # abort awaited read
|
||||||
if self._writer.is_closing():
|
if self._writer.is_closing():
|
||||||
return
|
return
|
||||||
logger.debug(f'AsyncStream.close() l{self.l_addr} | r{self.r_addr}')
|
logger.debug(f'AsyncStream.close() l{self.l_addr} | r{self.r_addr}')
|
||||||
self.ifc.write.reg_trigger(None)
|
|
||||||
self._writer.close()
|
self._writer.close()
|
||||||
|
|
||||||
def healthy(self) -> bool:
|
def healthy(self) -> bool:
|
||||||
elapsed = 0
|
elapsed = 0
|
||||||
if self.proc_start is not None:
|
if self.proc_start is not None:
|
||||||
elapsed = time.time() - self.proc_start
|
elapsed = time.time() - self.proc_start
|
||||||
if self.state == State.closed or elapsed > self.MAX_PROC_TIME:
|
if elapsed > self.MAX_PROC_TIME:
|
||||||
logging.debug(f'[{self.node_id}:{self.conn_no}:'
|
logging.debug(f'[{self.node_id}:{self.conn_no}:'
|
||||||
f'{type(self).__name__}]'
|
f'{type(self).__name__}]'
|
||||||
f' act:{round(1000*elapsed)}ms'
|
f' act:{round(1000*elapsed)}ms'
|
||||||
@@ -203,8 +299,8 @@ class AsyncStream():
|
|||||||
data = await self._reader.read(4096)
|
data = await self._reader.read(4096)
|
||||||
if data:
|
if data:
|
||||||
self.proc_start = time.time()
|
self.proc_start = time.time()
|
||||||
self.ifc.read += data
|
self.rx_fifo += data
|
||||||
wait = self.ifc.read() # call read in parent class
|
wait = self.rx_fifo() # call read in parent class
|
||||||
if wait > 0:
|
if wait > 0:
|
||||||
await asyncio.sleep(wait)
|
await asyncio.sleep(wait)
|
||||||
else:
|
else:
|
||||||
@@ -212,42 +308,42 @@ class AsyncStream():
|
|||||||
|
|
||||||
async def __async_forward(self) -> None:
|
async def __async_forward(self) -> None:
|
||||||
"""forward handler transmits data over the remote connection"""
|
"""forward handler transmits data over the remote connection"""
|
||||||
if len(self.ifc.forward) == 0:
|
if len(self.fwd_fifo) == 0:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
if not self.remote_stream:
|
if not self.remote.stream:
|
||||||
await self.async_create_remote()
|
await self.async_create_remote()
|
||||||
if self.remote_stream:
|
if self.remote.stream:
|
||||||
if self.remote_stream._init_new_client_conn():
|
if self.remote.stream._init_new_client_conn():
|
||||||
await self.remote_stream.__async_write()
|
await self.remote.stream._ifc.__async_write()
|
||||||
|
|
||||||
if self.remote_stream:
|
if self.remote.stream:
|
||||||
self.remote_stream._update_header(self.ifc.forward.peek())
|
self.remote.stream._update_header(self.fwd_fifo.peek())
|
||||||
self.ifc.forward.logging(logging.INFO, 'Forward to '
|
self.fwd_fifo.logging(logging.INFO, 'Forward to '
|
||||||
f'{self.remote_stream.addr}:')
|
f'{self.remote.stream.addr}:')
|
||||||
self.remote_stream._writer.write(self.ifc.forward.get())
|
self.remote.stream._ifc._writer.write(self.fwd_fifo.get())
|
||||||
await self.remote_stream._writer.drain()
|
await self.remote.stream._ifc._writer.drain()
|
||||||
|
|
||||||
except OSError as error:
|
except OSError as error:
|
||||||
if self.remote_stream:
|
if self.remote.stream:
|
||||||
rmt = self.remote_stream
|
rmt = self.remote.stream
|
||||||
self.remote_stream = None
|
self.remote.stream = None
|
||||||
logger.error(f'[{rmt.node_id}:{rmt.conn_no}] Fwd: {error} for '
|
logger.error(f'[{rmt.node_id}:{rmt.conn_no}] Fwd: {error} for '
|
||||||
f'l{rmt.l_addr} | r{rmt.r_addr}')
|
f'l{rmt._ifc.l_addr} | r{rmt._ifc.r_addr}')
|
||||||
await rmt.disc()
|
await rmt._ifc.disc()
|
||||||
rmt.close()
|
rmt._ifc.close()
|
||||||
|
|
||||||
except RuntimeError as error:
|
except RuntimeError as error:
|
||||||
if self.remote_stream:
|
if self.remote.stream:
|
||||||
rmt = self.remote_stream
|
rmt = self.remote.stream
|
||||||
self.remote_stream = None
|
self.remote.stream = None
|
||||||
logger.info(f'[{rmt.node_id}:{rmt.conn_no}] '
|
logger.info(f'[{rmt.node_id}:{rmt.conn_no}] '
|
||||||
f'Fwd: {error} for {rmt.l_addr}')
|
f'Fwd: {error} for {rmt._ifc.l_addr}')
|
||||||
await rmt.disc()
|
await rmt._ifc.disc()
|
||||||
rmt.close()
|
rmt._ifc.close()
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
self.inc_counter('SW_Exception')
|
Infos.inc_counter('SW_Exception')
|
||||||
logger.error(
|
logger.error(
|
||||||
f"Fwd Exception for {self.addr}:\n"
|
f"Fwd Exception for {self.addr}:\n"
|
||||||
f"{traceback.format_exc()}")
|
f"{traceback.format_exc()}")
|
||||||
|
|||||||
@@ -2,33 +2,35 @@ import logging
|
|||||||
from asyncio import StreamReader, StreamWriter
|
from asyncio import StreamReader, StreamWriter
|
||||||
|
|
||||||
if __name__ == "app.src.gen3.connection_g3":
|
if __name__ == "app.src.gen3.connection_g3":
|
||||||
from app.src.async_ifc import AsyncIfc
|
from app.src.async_stream import AsyncStream, StreamPtr
|
||||||
from app.src.async_stream import AsyncStream
|
|
||||||
from app.src.gen3.talent import Talent
|
from app.src.gen3.talent import Talent
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
from async_ifc import AsyncIfc
|
from async_stream import AsyncStream, StreamPtr
|
||||||
from async_stream import AsyncStream
|
|
||||||
from gen3.talent import Talent
|
from gen3.talent import Talent
|
||||||
|
|
||||||
logger = logging.getLogger('conn')
|
logger = logging.getLogger('conn')
|
||||||
|
|
||||||
|
|
||||||
class ConnectionG3(AsyncStream, Talent):
|
class ConnectionG3(Talent):
|
||||||
|
|
||||||
def __init__(self, reader: StreamReader, writer: StreamWriter,
|
def __init__(self, reader: StreamReader, writer: StreamWriter,
|
||||||
addr, remote_stream: 'ConnectionG3', server_side: bool,
|
addr, rstream: 'ConnectionG3', server_side: bool,
|
||||||
id_str=b'') -> None:
|
id_str=b'') -> None:
|
||||||
self._ifc = AsyncIfc()
|
self.remote = StreamPtr(rstream)
|
||||||
AsyncStream.__init__(self, reader, writer, addr, self._ifc)
|
self._ifc = AsyncStream(reader, writer, addr,
|
||||||
|
self.async_publ_mqtt,
|
||||||
|
self.async_create_remote,
|
||||||
|
self.remote)
|
||||||
Talent.__init__(self, server_side, self._ifc, id_str)
|
Talent.__init__(self, server_side, self._ifc, id_str)
|
||||||
|
|
||||||
self.remote_stream: 'ConnectionG3' = remote_stream
|
self.conn_no = self._ifc.get_conn_no()
|
||||||
|
self.addr = addr
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Our puplic methods
|
Our puplic methods
|
||||||
'''
|
'''
|
||||||
def close(self):
|
def close(self):
|
||||||
AsyncStream.close(self)
|
self._ifc.close()
|
||||||
Talent.close(self)
|
Talent.close(self)
|
||||||
# logger.info(f'AsyncStream refs: {gc.get_referrers(self)}')
|
# logger.info(f'AsyncStream refs: {gc.get_referrers(self)}')
|
||||||
|
|
||||||
@@ -40,10 +42,4 @@ class ConnectionG3(AsyncStream, Talent):
|
|||||||
|
|
||||||
def healthy(self) -> bool:
|
def healthy(self) -> bool:
|
||||||
logger.debug('ConnectionG3 healthy()')
|
logger.debug('ConnectionG3 healthy()')
|
||||||
return AsyncStream.healthy(self)
|
return self._ifc.healthy()
|
||||||
|
|
||||||
'''
|
|
||||||
Our private methods
|
|
||||||
'''
|
|
||||||
def __del__(self):
|
|
||||||
super().__del__()
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class InverterG3(Inverter, ConnectionG3):
|
|||||||
def __init__(self, reader: StreamReader, writer: StreamWriter, addr):
|
def __init__(self, reader: StreamReader, writer: StreamWriter, addr):
|
||||||
super().__init__(reader, writer, addr, None, True)
|
super().__init__(reader, writer, addr, None, True)
|
||||||
self.__ha_restarts = -1
|
self.__ha_restarts = -1
|
||||||
|
self.addr = addr
|
||||||
|
|
||||||
async def async_create_remote(self) -> None:
|
async def async_create_remote(self) -> None:
|
||||||
'''Establish a client connection to the TSUN cloud'''
|
'''Establish a client connection to the TSUN cloud'''
|
||||||
@@ -65,12 +66,12 @@ class InverterG3(Inverter, ConnectionG3):
|
|||||||
logging.info(f'[{self.node_id}] Connect to {addr}')
|
logging.info(f'[{self.node_id}] Connect to {addr}')
|
||||||
connect = asyncio.open_connection(host, port)
|
connect = asyncio.open_connection(host, port)
|
||||||
reader, writer = await connect
|
reader, writer = await connect
|
||||||
self.remote_stream = ConnectionG3(reader, writer, addr, self,
|
self.remote.stream = ConnectionG3(reader, writer, addr, self,
|
||||||
False, self.id_str)
|
False, self.id_str)
|
||||||
logging.info(f'[{self.remote_stream.node_id}:'
|
logging.info(f'[{self.remote.stream.node_id}:'
|
||||||
f'{self.remote_stream.conn_no}] '
|
f'{self.remote.stream.conn_no}] '
|
||||||
f'Connected to {addr}')
|
f'Connected to {addr}')
|
||||||
asyncio.create_task(self.client_loop(addr))
|
asyncio.create_task(self._ifc.client_loop(addr))
|
||||||
|
|
||||||
except (ConnectionRefusedError, TimeoutError) as error:
|
except (ConnectionRefusedError, TimeoutError) as error:
|
||||||
logging.info(f'{error}')
|
logging.info(f'{error}')
|
||||||
@@ -128,10 +129,6 @@ class InverterG3(Inverter, ConnectionG3):
|
|||||||
self.db.reg_clr_at_midnight(f'{self.entity_prfx}{self.node_id}')
|
self.db.reg_clr_at_midnight(f'{self.entity_prfx}{self.node_id}')
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
logging.debug(f'InverterG3.close() l{self.l_addr} | r{self.r_addr}')
|
logging.debug(f'InverterG3.close() {self.addr}')
|
||||||
super().close() # call close handler in the parent class
|
super().close() # call close handler in the parent class
|
||||||
# logging.info(f'Inverter refs: {gc.get_referrers(self)}')
|
# logging.info(f'Inverter refs: {gc.get_referrers(self)}')
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
logging.debug("InverterG3.__del__")
|
|
||||||
super().__del__()
|
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ class Talent(Message):
|
|||||||
|
|
||||||
def __init__(self, server_side: bool, ifc: "AsyncIfc", id_str=b''):
|
def __init__(self, server_side: bool, ifc: "AsyncIfc", id_str=b''):
|
||||||
super().__init__(server_side, self.send_modbus_cb, mb_timeout=15)
|
super().__init__(server_side, self.send_modbus_cb, mb_timeout=15)
|
||||||
ifc.read.reg_trigger(self.read)
|
ifc.rx_set_cb(self.read)
|
||||||
|
ifc.prot_set_timeout_cb(self._timeout)
|
||||||
self.ifc = ifc
|
self.ifc = ifc
|
||||||
self.await_conn_resp_cnt = 0
|
self.await_conn_resp_cnt = 0
|
||||||
self.id_str = id_str
|
self.id_str = id_str
|
||||||
@@ -107,7 +108,8 @@ class Talent(Message):
|
|||||||
self.log_lvl.clear()
|
self.log_lvl.clear()
|
||||||
self.state = State.closed
|
self.state = State.closed
|
||||||
self.mb_timer.close()
|
self.mb_timer.close()
|
||||||
self.ifc.read.reg_trigger(None)
|
self.ifc.rx_set_cb(None)
|
||||||
|
self.ifc.prot_set_timeout_cb(None)
|
||||||
super().close()
|
super().close()
|
||||||
|
|
||||||
def __set_serial_no(self, serial_no: str):
|
def __set_serial_no(self, serial_no: str):
|
||||||
@@ -143,10 +145,10 @@ class Talent(Message):
|
|||||||
self._read()
|
self._read()
|
||||||
while True:
|
while True:
|
||||||
if not self.header_valid:
|
if not self.header_valid:
|
||||||
self.__parse_header(self.ifc.read.peek(), len(self.ifc.read))
|
self.__parse_header(self.ifc.rx_peek(), self.ifc.rx_len())
|
||||||
|
|
||||||
if self.header_valid and \
|
if self.header_valid and \
|
||||||
len(self.ifc.read) >= (self.header_len + self.data_len):
|
self.ifc.rx_len() >= (self.header_len + self.data_len):
|
||||||
if self.state == State.init:
|
if self.state == State.init:
|
||||||
self.state = State.received # received 1st package
|
self.state = State.received # received 1st package
|
||||||
|
|
||||||
@@ -154,10 +156,10 @@ class Talent(Message):
|
|||||||
if callable(log_lvl):
|
if callable(log_lvl):
|
||||||
log_lvl = log_lvl()
|
log_lvl = log_lvl()
|
||||||
|
|
||||||
self.ifc.read.logging(log_lvl, f'Received from {self.addr}:'
|
self.ifc.rx_log(log_lvl, f'Received from {self.addr}:'
|
||||||
f' BufLen: {len(self.ifc.read)}'
|
f' BufLen: {self.ifc.rx_len()}'
|
||||||
f' HdrLen: {self.header_len}'
|
f' HdrLen: {self.header_len}'
|
||||||
f' DtaLen: {self.data_len}')
|
f' DtaLen: {self.data_len}')
|
||||||
|
|
||||||
self.__set_serial_no(self.id_str.decode("utf-8"))
|
self.__set_serial_no(self.id_str.decode("utf-8"))
|
||||||
self.__dispatch_msg()
|
self.__dispatch_msg()
|
||||||
@@ -170,9 +172,9 @@ class Talent(Message):
|
|||||||
tsun = Config.get('tsun')
|
tsun = Config.get('tsun')
|
||||||
if tsun['enabled']:
|
if tsun['enabled']:
|
||||||
buflen = self.header_len+self.data_len
|
buflen = self.header_len+self.data_len
|
||||||
buffer = self.ifc.read.peek(buflen)
|
buffer = self.ifc.rx_peek(buflen)
|
||||||
self.ifc.forward += buffer
|
self.ifc.fwd_add(buffer)
|
||||||
self.ifc.forward.logging(logging.DEBUG, 'Store for forwarding:')
|
self.ifc.fwd_log(logging.DEBUG, 'Store for forwarding:')
|
||||||
|
|
||||||
fnc = self.switch.get(self.msg_id, self.msg_unknown)
|
fnc = self.switch.get(self.msg_id, self.msg_unknown)
|
||||||
logger.info(self.__flow_str(self.server_side, 'forwrd') +
|
logger.info(self.__flow_str(self.server_side, 'forwrd') +
|
||||||
@@ -181,18 +183,18 @@ class Talent(Message):
|
|||||||
def forward_snd(self) -> None:
|
def forward_snd(self) -> None:
|
||||||
'''add the build send msg to the forwarding queue'''
|
'''add the build send msg to the forwarding queue'''
|
||||||
tsun = Config.get('tsun')
|
tsun = Config.get('tsun')
|
||||||
rest = self.ifc.write.get(self.send_msg_ofs)
|
rest = self.ifc.tx_get(self.send_msg_ofs)
|
||||||
buffer = self.ifc.write.get(len(self.ifc.write))
|
buffer = self.ifc.tx_get()
|
||||||
if tsun['enabled']:
|
if tsun['enabled']:
|
||||||
_len = len(buffer)
|
_len = len(buffer)
|
||||||
struct.pack_into('!l', buffer, 0, _len-4)
|
struct.pack_into('!l', buffer, 0, _len-4)
|
||||||
self.ifc.forward += buffer
|
self.ifc.fwd_add(buffer)
|
||||||
self.ifc.forward.logging(logging.INFO, 'Store for forwarding:')
|
self.ifc.fwd_log(logging.INFO, 'Store for forwarding:')
|
||||||
|
|
||||||
fnc = self.switch.get(self.msg_id, self.msg_unknown)
|
fnc = self.switch.get(self.msg_id, self.msg_unknown)
|
||||||
logger.info(self.__flow_str(self.server_side, 'forwrd') +
|
logger.info(self.__flow_str(self.server_side, 'forwrd') +
|
||||||
f' Ctl: {int(self.ctrl):#02x} Msg: {fnc.__name__!r}')
|
f' Ctl: {int(self.ctrl):#02x} Msg: {fnc.__name__!r}')
|
||||||
self.ifc.write += rest
|
self.ifc.tx_add(rest)
|
||||||
|
|
||||||
def send_modbus_cb(self, modbus_pdu: bytearray, log_lvl: int, state: str):
|
def send_modbus_cb(self, modbus_pdu: bytearray, log_lvl: int, state: str):
|
||||||
if self.state != State.up:
|
if self.state != State.up:
|
||||||
@@ -201,13 +203,13 @@ class Talent(Message):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.__build_header(0x70, 0x77)
|
self.__build_header(0x70, 0x77)
|
||||||
self.ifc.write += b'\x00\x01\xa3\x28' # magic ?
|
self.ifc.tx_add(b'\x00\x01\xa3\x28') # magic ?
|
||||||
self.ifc.write += struct.pack('!B', len(modbus_pdu))
|
self.ifc.tx_add(struct.pack('!B', len(modbus_pdu)))
|
||||||
self.ifc.write += modbus_pdu
|
self.ifc.tx_add(modbus_pdu)
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
|
|
||||||
self.ifc.write.logging(log_lvl, f'Send Modbus {state}:{self.addr}:')
|
self.ifc.tx_log(log_lvl, f'Send Modbus {state}:{self.addr}:')
|
||||||
self.ifc.write()
|
self.ifc.tx_flush()
|
||||||
|
|
||||||
def _send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
|
def _send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
|
||||||
if self.state != State.up:
|
if self.state != State.up:
|
||||||
@@ -235,9 +237,9 @@ class Talent(Message):
|
|||||||
self.msg_id = 0
|
self.msg_id = 0
|
||||||
self.await_conn_resp_cnt += 1
|
self.await_conn_resp_cnt += 1
|
||||||
self.__build_header(0x91)
|
self.__build_header(0x91)
|
||||||
self.ifc.write += struct.pack(f'!{len(contact_name)+1}p'
|
self.ifc.tx_add(struct.pack(f'!{len(contact_name)+1}p'
|
||||||
f'{len(contact_mail)+1}p',
|
f'{len(contact_mail)+1}p',
|
||||||
contact_name, contact_mail)
|
contact_name, contact_mail))
|
||||||
|
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
return True
|
return True
|
||||||
@@ -321,7 +323,7 @@ class Talent(Message):
|
|||||||
self.inc_counter('Invalid_Msg_Format')
|
self.inc_counter('Invalid_Msg_Format')
|
||||||
|
|
||||||
# erase broken recv buffer
|
# erase broken recv buffer
|
||||||
self.ifc.read.clear()
|
self.ifc.rx_clear()
|
||||||
return
|
return
|
||||||
|
|
||||||
hdr_len = 5+id_len+2
|
hdr_len = 5+id_len+2
|
||||||
@@ -342,16 +344,16 @@ class Talent(Message):
|
|||||||
def __build_header(self, ctrl, msg_id=None) -> None:
|
def __build_header(self, ctrl, msg_id=None) -> None:
|
||||||
if not msg_id:
|
if not msg_id:
|
||||||
msg_id = self.msg_id
|
msg_id = self.msg_id
|
||||||
self.send_msg_ofs = len(self.ifc.write)
|
self.send_msg_ofs = self.ifc.tx_len()
|
||||||
self.ifc.write += struct.pack(f'!l{len(self.id_str)+1}pBB',
|
self.ifc.tx_add(struct.pack(f'!l{len(self.id_str)+1}pBB',
|
||||||
0, self.id_str, ctrl, msg_id)
|
0, self.id_str, ctrl, msg_id))
|
||||||
fnc = self.switch.get(msg_id, self.msg_unknown)
|
fnc = self.switch.get(msg_id, self.msg_unknown)
|
||||||
logger.info(self.__flow_str(self.server_side, 'tx') +
|
logger.info(self.__flow_str(self.server_side, 'tx') +
|
||||||
f' Ctl: {int(ctrl):#02x} Msg: {fnc.__name__!r}')
|
f' Ctl: {int(ctrl):#02x} Msg: {fnc.__name__!r}')
|
||||||
|
|
||||||
def __finish_send_msg(self) -> None:
|
def __finish_send_msg(self) -> None:
|
||||||
_len = len(self.ifc.write) - self.send_msg_ofs
|
_len = self.ifc.tx_len() - self.send_msg_ofs
|
||||||
struct.pack_into('!l', self.ifc.write.peek(), self.send_msg_ofs,
|
struct.pack_into('!l', self.ifc.tx_peek(), self.send_msg_ofs,
|
||||||
_len-4)
|
_len-4)
|
||||||
|
|
||||||
def __dispatch_msg(self) -> None:
|
def __dispatch_msg(self) -> None:
|
||||||
@@ -366,7 +368,7 @@ class Talent(Message):
|
|||||||
f' Ctl: {int(self.ctrl):#02x} Msg: {fnc.__name__!r}')
|
f' Ctl: {int(self.ctrl):#02x} Msg: {fnc.__name__!r}')
|
||||||
|
|
||||||
def __flush_recv_msg(self) -> None:
|
def __flush_recv_msg(self) -> None:
|
||||||
self.ifc.read.get(self.header_len+self.data_len)
|
self.ifc.rx_get(self.header_len+self.data_len)
|
||||||
self.header_valid = False
|
self.header_valid = False
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@@ -376,7 +378,7 @@ class Talent(Message):
|
|||||||
if self.ctrl.is_ind():
|
if self.ctrl.is_ind():
|
||||||
if self.server_side and self.__process_contact_info():
|
if self.server_side and self.__process_contact_info():
|
||||||
self.__build_header(0x91)
|
self.__build_header(0x91)
|
||||||
self.ifc.write += b'\x01'
|
self.ifc.tx_add(b'\x01')
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
# don't forward this contact info here, we will build one
|
# don't forward this contact info here, we will build one
|
||||||
# when the remote connection is established
|
# when the remote connection is established
|
||||||
@@ -390,7 +392,7 @@ class Talent(Message):
|
|||||||
self.forward()
|
self.forward()
|
||||||
|
|
||||||
def __process_contact_info(self) -> bool:
|
def __process_contact_info(self) -> bool:
|
||||||
buf = self.ifc.read.peek()
|
buf = self.ifc.rx_peek()
|
||||||
result = struct.unpack_from('!B', buf, self.header_len)
|
result = struct.unpack_from('!B', buf, self.header_len)
|
||||||
name_len = result[0]
|
name_len = result[0]
|
||||||
if self.data_len == 1: # this is a response withone status byte
|
if self.data_len == 1: # this is a response withone status byte
|
||||||
@@ -417,16 +419,16 @@ class Talent(Message):
|
|||||||
ts = self._timestamp()
|
ts = self._timestamp()
|
||||||
logger.debug(f'time: {ts:08x}')
|
logger.debug(f'time: {ts:08x}')
|
||||||
self.__build_header(0x91)
|
self.__build_header(0x91)
|
||||||
self.ifc.write += struct.pack('!q', ts)
|
self.ifc.tx_add(struct.pack('!q', ts))
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
|
|
||||||
elif self.data_len >= 8:
|
elif self.data_len >= 8:
|
||||||
ts = self._timestamp()
|
ts = self._timestamp()
|
||||||
result = struct.unpack_from('!q', self.ifc.read.peek(),
|
result = struct.unpack_from('!q', self.ifc.rx_peek(),
|
||||||
self.header_len)
|
self.header_len)
|
||||||
self.ts_offset = result[0]-ts
|
self.ts_offset = result[0]-ts
|
||||||
if self.remote_stream:
|
if self.remote.stream:
|
||||||
self.remote_stream.ts_offset = self.ts_offset
|
self.remote.stream.ts_offset = self.ts_offset
|
||||||
logger.debug(f'tsun-time: {int(result[0]):08x}'
|
logger.debug(f'tsun-time: {int(result[0]):08x}'
|
||||||
f' proxy-time: {ts:08x}'
|
f' proxy-time: {ts:08x}'
|
||||||
f' offset: {self.ts_offset}')
|
f' offset: {self.ts_offset}')
|
||||||
@@ -446,10 +448,10 @@ class Talent(Message):
|
|||||||
self.db.set_db_def_value(Register.POLLING_INTERVAL,
|
self.db.set_db_def_value(Register.POLLING_INTERVAL,
|
||||||
self.mb_timeout)
|
self.mb_timeout)
|
||||||
self.__build_header(0x99)
|
self.__build_header(0x99)
|
||||||
self.ifc.write += b'\x02'
|
self.ifc.tx_add(b'\x02')
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
|
|
||||||
result = struct.unpack_from('!Bq', self.ifc.read.peek(),
|
result = struct.unpack_from('!Bq', self.ifc.rx_peek(),
|
||||||
self.header_len)
|
self.header_len)
|
||||||
resp_code = result[0]
|
resp_code = result[0]
|
||||||
ts = result[1]+self.ts_offset
|
ts = result[1]+self.ts_offset
|
||||||
@@ -457,11 +459,11 @@ class Talent(Message):
|
|||||||
f' tsun-time: {ts:08x}'
|
f' tsun-time: {ts:08x}'
|
||||||
f' offset: {self.ts_offset}')
|
f' offset: {self.ts_offset}')
|
||||||
self.__build_header(0x91)
|
self.__build_header(0x91)
|
||||||
self.ifc.write += struct.pack('!Bq', resp_code, ts)
|
self.ifc.tx_add(struct.pack('!Bq', resp_code, ts))
|
||||||
self.forward_snd()
|
self.forward_snd()
|
||||||
return
|
return
|
||||||
elif self.ctrl.is_resp():
|
elif self.ctrl.is_resp():
|
||||||
result = struct.unpack_from('!B', self.ifc.read.peek(),
|
result = struct.unpack_from('!B', self.ifc.rx_peek(),
|
||||||
self.header_len)
|
self.header_len)
|
||||||
resp_code = result[0]
|
resp_code = result[0]
|
||||||
logging.debug(f'TimeActRespCode: {resp_code}')
|
logging.debug(f'TimeActRespCode: {resp_code}')
|
||||||
@@ -473,7 +475,7 @@ class Talent(Message):
|
|||||||
self.forward()
|
self.forward()
|
||||||
|
|
||||||
def parse_msg_header(self):
|
def parse_msg_header(self):
|
||||||
result = struct.unpack_from('!lB', self.ifc.read.peek(),
|
result = struct.unpack_from('!lB', self.ifc.rx_peek(),
|
||||||
self.header_len)
|
self.header_len)
|
||||||
|
|
||||||
data_id = result[0] # len of complete message
|
data_id = result[0] # len of complete message
|
||||||
@@ -482,7 +484,7 @@ class Talent(Message):
|
|||||||
|
|
||||||
msg_hdr_len = 5+id_len+9
|
msg_hdr_len = 5+id_len+9
|
||||||
|
|
||||||
result = struct.unpack_from(f'!{id_len+1}pBq', self.ifc.read.peek(),
|
result = struct.unpack_from(f'!{id_len+1}pBq', self.ifc.rx_peek(),
|
||||||
self.header_len + 4)
|
self.header_len + 4)
|
||||||
|
|
||||||
timestamp = result[2]
|
timestamp = result[2]
|
||||||
@@ -495,7 +497,7 @@ class Talent(Message):
|
|||||||
def msg_collector_data(self):
|
def msg_collector_data(self):
|
||||||
if self.ctrl.is_ind():
|
if self.ctrl.is_ind():
|
||||||
self.__build_header(0x99)
|
self.__build_header(0x99)
|
||||||
self.ifc.write += b'\x01'
|
self.ifc.tx_add(b'\x01')
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
self.__process_data()
|
self.__process_data()
|
||||||
|
|
||||||
@@ -510,7 +512,7 @@ class Talent(Message):
|
|||||||
def msg_inverter_data(self):
|
def msg_inverter_data(self):
|
||||||
if self.ctrl.is_ind():
|
if self.ctrl.is_ind():
|
||||||
self.__build_header(0x99)
|
self.__build_header(0x99)
|
||||||
self.ifc.write += b'\x01'
|
self.ifc.tx_add(b'\x01')
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
self.__process_data()
|
self.__process_data()
|
||||||
self.state = State.up # allow MODBUS cmds
|
self.state = State.up # allow MODBUS cmds
|
||||||
@@ -530,7 +532,7 @@ class Talent(Message):
|
|||||||
def __process_data(self):
|
def __process_data(self):
|
||||||
msg_hdr_len, ts = self.parse_msg_header()
|
msg_hdr_len, ts = self.parse_msg_header()
|
||||||
|
|
||||||
for key, update in self.db.parse(self.ifc.read.peek(), self.header_len
|
for key, update in self.db.parse(self.ifc.rx_peek(), self.header_len
|
||||||
+ msg_hdr_len, self.node_id):
|
+ msg_hdr_len, self.node_id):
|
||||||
if update:
|
if update:
|
||||||
self._set_mqtt_timestamp(key, self._utcfromts(ts))
|
self._set_mqtt_timestamp(key, self._utcfromts(ts))
|
||||||
@@ -550,7 +552,7 @@ class Talent(Message):
|
|||||||
|
|
||||||
msg_hdr_len = 5
|
msg_hdr_len = 5
|
||||||
|
|
||||||
result = struct.unpack_from('!lBB', self.ifc.read.peek(),
|
result = struct.unpack_from('!lBB', self.ifc.rx_peek(),
|
||||||
self.header_len)
|
self.header_len)
|
||||||
modbus_len = result[1]
|
modbus_len = result[1]
|
||||||
return msg_hdr_len, modbus_len
|
return msg_hdr_len, modbus_len
|
||||||
@@ -559,7 +561,7 @@ class Talent(Message):
|
|||||||
|
|
||||||
msg_hdr_len = 6
|
msg_hdr_len = 6
|
||||||
|
|
||||||
result = struct.unpack_from('!lBBB', self.ifc.read.peek(),
|
result = struct.unpack_from('!lBBB', self.ifc.rx_peek(),
|
||||||
self.header_len)
|
self.header_len)
|
||||||
modbus_len = result[2]
|
modbus_len = result[2]
|
||||||
return msg_hdr_len, modbus_len
|
return msg_hdr_len, modbus_len
|
||||||
@@ -580,12 +582,12 @@ class Talent(Message):
|
|||||||
self.__msg_modbus(hdr_len)
|
self.__msg_modbus(hdr_len)
|
||||||
|
|
||||||
def __msg_modbus(self, hdr_len):
|
def __msg_modbus(self, hdr_len):
|
||||||
data = self.ifc.read.peek()[self.header_len:
|
data = self.ifc.rx_peek()[self.header_len:
|
||||||
self.header_len+self.data_len]
|
self.header_len+self.data_len]
|
||||||
|
|
||||||
if self.ctrl.is_req():
|
if self.ctrl.is_req():
|
||||||
if self.remote_stream.mb.recv_req(data[hdr_len:],
|
if self.remote.stream.mb.recv_req(data[hdr_len:],
|
||||||
self.remote_stream.
|
self.remote.stream.
|
||||||
msg_forward):
|
msg_forward):
|
||||||
self.inc_counter('Modbus_Command')
|
self.inc_counter('Modbus_Command')
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -2,34 +2,37 @@ import logging
|
|||||||
from asyncio import StreamReader, StreamWriter
|
from asyncio import StreamReader, StreamWriter
|
||||||
|
|
||||||
if __name__ == "app.src.gen3plus.connection_g3p":
|
if __name__ == "app.src.gen3plus.connection_g3p":
|
||||||
from app.src.async_ifc import AsyncIfc
|
from app.src.async_stream import AsyncStream, StreamPtr
|
||||||
from app.src.async_stream import AsyncStream
|
|
||||||
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
from async_ifc import AsyncIfc
|
from async_stream import AsyncStream, StreamPtr
|
||||||
from async_stream import AsyncStream
|
|
||||||
from gen3plus.solarman_v5 import SolarmanV5
|
from gen3plus.solarman_v5 import SolarmanV5
|
||||||
|
|
||||||
logger = logging.getLogger('conn')
|
logger = logging.getLogger('conn')
|
||||||
|
|
||||||
|
|
||||||
class ConnectionG3P(AsyncStream, SolarmanV5):
|
class ConnectionG3P(SolarmanV5):
|
||||||
|
|
||||||
def __init__(self, reader: StreamReader, writer: StreamWriter,
|
def __init__(self, reader: StreamReader, writer: StreamWriter,
|
||||||
addr, remote_stream: 'ConnectionG3P',
|
addr, rstream: 'ConnectionG3P',
|
||||||
server_side: bool,
|
server_side: bool,
|
||||||
client_mode: bool) -> None:
|
client_mode: bool) -> None:
|
||||||
self._ifc = AsyncIfc()
|
|
||||||
AsyncStream.__init__(self, reader, writer, addr, self._ifc)
|
self.remote = StreamPtr(rstream)
|
||||||
|
self._ifc = AsyncStream(reader, writer, addr,
|
||||||
|
self.async_publ_mqtt,
|
||||||
|
self.async_create_remote,
|
||||||
|
self.remote)
|
||||||
SolarmanV5.__init__(self, server_side, client_mode, self._ifc)
|
SolarmanV5.__init__(self, server_side, client_mode, self._ifc)
|
||||||
|
|
||||||
self.remote_stream: 'ConnectionG3P' = remote_stream
|
self.conn_no = self._ifc.get_conn_no()
|
||||||
|
self.addr = addr
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Our puplic methods
|
Our puplic methods
|
||||||
'''
|
'''
|
||||||
def close(self):
|
def close(self):
|
||||||
AsyncStream.close(self)
|
self._ifc.close()
|
||||||
SolarmanV5.close(self)
|
SolarmanV5.close(self)
|
||||||
# logger.info(f'AsyncStream refs: {gc.get_referrers(self)}')
|
# logger.info(f'AsyncStream refs: {gc.get_referrers(self)}')
|
||||||
|
|
||||||
@@ -41,10 +44,4 @@ class ConnectionG3P(AsyncStream, SolarmanV5):
|
|||||||
|
|
||||||
def healthy(self) -> bool:
|
def healthy(self) -> bool:
|
||||||
logger.debug('ConnectionG3P healthy()')
|
logger.debug('ConnectionG3P healthy()')
|
||||||
return AsyncStream.healthy(self)
|
return self._ifc.healthy()
|
||||||
|
|
||||||
'''
|
|
||||||
Our private methods
|
|
||||||
'''
|
|
||||||
def __del__(self):
|
|
||||||
super().__del__()
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class InverterG3P(Inverter, ConnectionG3P):
|
|||||||
super().__init__(reader, writer, addr, None,
|
super().__init__(reader, writer, addr, None,
|
||||||
server_side=True, client_mode=client_mode)
|
server_side=True, client_mode=client_mode)
|
||||||
self.__ha_restarts = -1
|
self.__ha_restarts = -1
|
||||||
|
self.addr = addr
|
||||||
|
|
||||||
async def async_create_remote(self) -> None:
|
async def async_create_remote(self) -> None:
|
||||||
'''Establish a client connection to the TSUN cloud'''
|
'''Establish a client connection to the TSUN cloud'''
|
||||||
@@ -67,13 +68,13 @@ class InverterG3P(Inverter, ConnectionG3P):
|
|||||||
logging.info(f'[{self.node_id}] Connect to {addr}')
|
logging.info(f'[{self.node_id}] Connect to {addr}')
|
||||||
connect = asyncio.open_connection(host, port)
|
connect = asyncio.open_connection(host, port)
|
||||||
reader, writer = await connect
|
reader, writer = await connect
|
||||||
self.remote_stream = ConnectionG3P(reader, writer, addr, self,
|
self.remote.stream = ConnectionG3P(reader, writer, addr, self,
|
||||||
server_side=False,
|
server_side=False,
|
||||||
client_mode=False)
|
client_mode=False)
|
||||||
logging.info(f'[{self.remote_stream.node_id}:'
|
logging.info(f'[{self.remote.stream.node_id}:'
|
||||||
f'{self.remote_stream.conn_no}] '
|
f'{self.remote.stream.conn_no}] '
|
||||||
f'Connected to {addr}')
|
f'Connected to {addr}')
|
||||||
asyncio.create_task(self.client_loop(addr))
|
asyncio.create_task(self._ifc.client_loop(addr))
|
||||||
|
|
||||||
except (ConnectionRefusedError, TimeoutError) as error:
|
except (ConnectionRefusedError, TimeoutError) as error:
|
||||||
logging.info(f'{error}')
|
logging.info(f'{error}')
|
||||||
@@ -131,10 +132,6 @@ class InverterG3P(Inverter, ConnectionG3P):
|
|||||||
self.db.reg_clr_at_midnight(f'{self.entity_prfx}{self.node_id}')
|
self.db.reg_clr_at_midnight(f'{self.entity_prfx}{self.node_id}')
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
logging.debug(f'InverterG3P.close() l{self.l_addr} | r{self.r_addr}')
|
logging.debug(f'InverterG3P.close() {self.addr}')
|
||||||
super().close() # call close handler in the parent class
|
super().close() # call close handler in the parent class
|
||||||
# logger.debug (f'Inverter refs: {gc.get_referrers(self)}')
|
# logger.debug (f'Inverter refs: {gc.get_referrers(self)}')
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
logging.debug("InverterG3P.__del__")
|
|
||||||
super().__del__()
|
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ class SolarmanV5(Message):
|
|||||||
|
|
||||||
def __init__(self, server_side: bool, client_mode: bool, ifc: "AsyncIfc"):
|
def __init__(self, server_side: bool, client_mode: bool, ifc: "AsyncIfc"):
|
||||||
super().__init__(server_side, self.send_modbus_cb, mb_timeout=8)
|
super().__init__(server_side, self.send_modbus_cb, mb_timeout=8)
|
||||||
ifc.read.reg_trigger(self.read)
|
ifc.rx_set_cb(self.read)
|
||||||
|
ifc.prot_set_timeout_cb(self._timeout)
|
||||||
self.ifc = ifc
|
self.ifc = ifc
|
||||||
self.header_len = 11 # overwrite construcor in class Message
|
self.header_len = 11 # overwrite construcor in class Message
|
||||||
self.control = 0
|
self.control = 0
|
||||||
@@ -163,7 +164,8 @@ class SolarmanV5(Message):
|
|||||||
self.log_lvl.clear()
|
self.log_lvl.clear()
|
||||||
self.state = State.closed
|
self.state = State.closed
|
||||||
self.mb_timer.close()
|
self.mb_timer.close()
|
||||||
self.ifc.read.reg_trigger(None)
|
self.ifc.rx_set_cb(None)
|
||||||
|
self.ifc.prot_set_timeout_cb(None)
|
||||||
super().close()
|
super().close()
|
||||||
|
|
||||||
async def send_start_cmd(self, snr: int, host: str,
|
async def send_start_cmd(self, snr: int, host: str,
|
||||||
@@ -234,10 +236,10 @@ class SolarmanV5(Message):
|
|||||||
self._read()
|
self._read()
|
||||||
while True:
|
while True:
|
||||||
if not self.header_valid:
|
if not self.header_valid:
|
||||||
self.__parse_header(self.ifc.read.peek(),
|
self.__parse_header(self.ifc.rx_peek(),
|
||||||
len(self.ifc.read))
|
self.ifc.rx_len())
|
||||||
|
|
||||||
if self.header_valid and len(self.ifc.read) >= \
|
if self.header_valid and self.ifc.rx_len() >= \
|
||||||
(self.header_len + self.data_len+2):
|
(self.header_len + self.data_len+2):
|
||||||
self.__process_complete_received_msg()
|
self.__process_complete_received_msg()
|
||||||
self.__flush_recv_msg()
|
self.__flush_recv_msg()
|
||||||
@@ -248,10 +250,10 @@ class SolarmanV5(Message):
|
|||||||
log_lvl = self.log_lvl.get(self.control, logging.WARNING)
|
log_lvl = self.log_lvl.get(self.control, logging.WARNING)
|
||||||
if callable(log_lvl):
|
if callable(log_lvl):
|
||||||
log_lvl = log_lvl()
|
log_lvl = log_lvl()
|
||||||
self.ifc.read.logging(log_lvl, f'Received from {self.addr}:')
|
self.ifc.rx_log(log_lvl, f'Received from {self.addr}:')
|
||||||
# self._recv_buffer, self.header_len +
|
# self._recv_buffer, self.header_len +
|
||||||
# self.data_len+2)
|
# self.data_len+2)
|
||||||
if self.__trailer_is_ok(self.ifc.read.peek(), self.header_len
|
if self.__trailer_is_ok(self.ifc.rx_peek(), self.header_len
|
||||||
+ self.data_len + 2):
|
+ self.data_len + 2):
|
||||||
if self.state == State.init:
|
if self.state == State.init:
|
||||||
self.state = State.received
|
self.state = State.received
|
||||||
@@ -264,8 +266,8 @@ class SolarmanV5(Message):
|
|||||||
return
|
return
|
||||||
tsun = Config.get('solarman')
|
tsun = Config.get('solarman')
|
||||||
if tsun['enabled']:
|
if tsun['enabled']:
|
||||||
self.ifc.forward += buffer[:buflen]
|
self.ifc.fwd_add(buffer[:buflen])
|
||||||
self.ifc.forward.logging(logging.DEBUG, 'Store for forwarding:')
|
self.ifc.fwd_log(logging.DEBUG, 'Store for forwarding:')
|
||||||
|
|
||||||
fnc = self.switch.get(self.control, self.msg_unknown)
|
fnc = self.switch.get(self.control, self.msg_unknown)
|
||||||
logger.info(self.__flow_str(self.server_side, 'forwrd') +
|
logger.info(self.__flow_str(self.server_side, 'forwrd') +
|
||||||
@@ -321,7 +323,7 @@ class SolarmanV5(Message):
|
|||||||
|
|
||||||
self.inc_counter('Invalid_Msg_Format')
|
self.inc_counter('Invalid_Msg_Format')
|
||||||
# erase broken recv buffer
|
# erase broken recv buffer
|
||||||
self.ifc.read.clear()
|
self.ifc.rx_clear()
|
||||||
return
|
return
|
||||||
self.header_valid = True
|
self.header_valid = True
|
||||||
|
|
||||||
@@ -333,11 +335,11 @@ class SolarmanV5(Message):
|
|||||||
'Drop packet w invalid stop byte from '
|
'Drop packet w invalid stop byte from '
|
||||||
f'{self.addr}:', buf, buf_len)
|
f'{self.addr}:', buf, buf_len)
|
||||||
self.inc_counter('Invalid_Msg_Format')
|
self.inc_counter('Invalid_Msg_Format')
|
||||||
if len(self.ifc.read) > (self.data_len+13):
|
if self.ifc.rx_len() > (self.data_len+13):
|
||||||
next_start = buf[self.data_len+13]
|
next_start = buf[self.data_len+13]
|
||||||
if next_start != 0xa5:
|
if next_start != 0xa5:
|
||||||
# erase broken recv buffer
|
# erase broken recv buffer
|
||||||
self.ifc.read.clear()
|
self.ifc.rx_clear()
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -353,22 +355,22 @@ class SolarmanV5(Message):
|
|||||||
|
|
||||||
def __build_header(self, ctrl) -> None:
|
def __build_header(self, ctrl) -> None:
|
||||||
'''build header for new transmit message'''
|
'''build header for new transmit message'''
|
||||||
self.send_msg_ofs = len(self.ifc.write)
|
self.send_msg_ofs = self.ifc.tx_len()
|
||||||
|
|
||||||
self.ifc.write += struct.pack(
|
self.ifc.tx_add(struct.pack(
|
||||||
'<BHHHL', 0xA5, 0, ctrl, self.seq.get_send(), self.snr)
|
'<BHHHL', 0xA5, 0, ctrl, self.seq.get_send(), self.snr))
|
||||||
fnc = self.switch.get(ctrl, self.msg_unknown)
|
fnc = self.switch.get(ctrl, self.msg_unknown)
|
||||||
logger.info(self.__flow_str(self.server_side, 'tx') +
|
logger.info(self.__flow_str(self.server_side, 'tx') +
|
||||||
f' Ctl: {int(ctrl):#04x} Msg: {fnc.__name__!r}')
|
f' Ctl: {int(ctrl):#04x} Msg: {fnc.__name__!r}')
|
||||||
|
|
||||||
def __finish_send_msg(self) -> None:
|
def __finish_send_msg(self) -> None:
|
||||||
'''finish the transmit message, set lenght and checksum'''
|
'''finish the transmit message, set lenght and checksum'''
|
||||||
_len = len(self.ifc.write) - self.send_msg_ofs
|
_len = self.ifc.tx_len() - self.send_msg_ofs
|
||||||
struct.pack_into('<H', self.ifc.write.peek(), self.send_msg_ofs+1,
|
struct.pack_into('<H', self.ifc.tx_peek(), self.send_msg_ofs+1,
|
||||||
_len-11)
|
_len-11)
|
||||||
check = sum(self.ifc.write.peek()[
|
check = sum(self.ifc.tx_peek()[
|
||||||
self.send_msg_ofs+1:self.send_msg_ofs + _len]) & 0xff
|
self.send_msg_ofs+1:self.send_msg_ofs + _len]) & 0xff
|
||||||
self.ifc.write += struct.pack('<BB', check, 0x15) # crc & stop
|
self.ifc.tx_add(struct.pack('<BB', check, 0x15)) # crc & stop
|
||||||
|
|
||||||
def _update_header(self, _forward_buffer):
|
def _update_header(self, _forward_buffer):
|
||||||
'''update header for message before forwarding,
|
'''update header for message before forwarding,
|
||||||
@@ -399,14 +401,14 @@ class SolarmanV5(Message):
|
|||||||
f' Msg: {fnc.__name__!r}')
|
f' Msg: {fnc.__name__!r}')
|
||||||
|
|
||||||
def __flush_recv_msg(self) -> None:
|
def __flush_recv_msg(self) -> None:
|
||||||
self.ifc.read.get(self.header_len + self.data_len+2)
|
self.ifc.rx_get(self.header_len + self.data_len+2)
|
||||||
self.header_valid = False
|
self.header_valid = False
|
||||||
|
|
||||||
def __send_ack_rsp(self, msgtype, ftype, ack=1):
|
def __send_ack_rsp(self, msgtype, ftype, ack=1):
|
||||||
self.__build_header(msgtype)
|
self.__build_header(msgtype)
|
||||||
self.ifc.write += struct.pack('<BBLL', ftype, ack,
|
self.ifc.tx_add(struct.pack('<BBLL', ftype, ack,
|
||||||
self._timestamp(),
|
self._timestamp(),
|
||||||
self._heartbeat())
|
self._heartbeat()))
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
|
|
||||||
def send_modbus_cb(self, pdu: bytearray, log_lvl: int, state: str):
|
def send_modbus_cb(self, pdu: bytearray, log_lvl: int, state: str):
|
||||||
@@ -415,12 +417,12 @@ class SolarmanV5(Message):
|
|||||||
' cause the state is not UP anymore')
|
' cause the state is not UP anymore')
|
||||||
return
|
return
|
||||||
self.__build_header(0x4510)
|
self.__build_header(0x4510)
|
||||||
self.ifc.write += struct.pack('<BHLLL', self.MB_RTU_CMD,
|
self.ifc.tx_add(struct.pack('<BHLLL', self.MB_RTU_CMD,
|
||||||
self.sensor_list, 0, 0, 0)
|
self.sensor_list, 0, 0, 0))
|
||||||
self.ifc.write += pdu
|
self.ifc.tx_add(pdu)
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
self.ifc.write.logging(log_lvl, f'Send Modbus {state}:{self.addr}:')
|
self.ifc.tx_log(log_lvl, f'Send Modbus {state}:{self.addr}:')
|
||||||
self.ifc.write()
|
self.ifc.tx_flush()
|
||||||
|
|
||||||
def _send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
|
def _send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
|
||||||
if self.state != State.up:
|
if self.state != State.up:
|
||||||
@@ -462,18 +464,18 @@ class SolarmanV5(Message):
|
|||||||
|
|
||||||
self.forward_at_cmd_resp = False
|
self.forward_at_cmd_resp = False
|
||||||
self.__build_header(0x4510)
|
self.__build_header(0x4510)
|
||||||
self.ifc.write += struct.pack(f'<BHLLL{len(at_cmd)}sc', self.AT_CMD,
|
self.ifc.tx_add(struct.pack(f'<BHLLL{len(at_cmd)}sc', self.AT_CMD,
|
||||||
0x0002, 0, 0, 0,
|
0x0002, 0, 0, 0,
|
||||||
at_cmd.encode('utf-8'), b'\r')
|
at_cmd.encode('utf-8'), b'\r'))
|
||||||
self.__finish_send_msg()
|
self.__finish_send_msg()
|
||||||
self.ifc.write.logging(logging.INFO, 'Send AT Command:')
|
self.ifc.tx_log(logging.INFO, 'Send AT Command:')
|
||||||
try:
|
try:
|
||||||
self.ifc.write()
|
self.ifc.tx_flush()
|
||||||
except Exception:
|
except Exception:
|
||||||
self.ifc.write.clear()
|
self.ifc.tx_clear()
|
||||||
|
|
||||||
def __forward_msg(self):
|
def __forward_msg(self):
|
||||||
self.forward(self.ifc.read.peek(), self.header_len+self.data_len+2)
|
self.forward(self.ifc.rx_peek(), self.header_len+self.data_len+2)
|
||||||
|
|
||||||
def __build_model_name(self):
|
def __build_model_name(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
@@ -494,7 +496,7 @@ class SolarmanV5(Message):
|
|||||||
def __process_data(self, ftype, ts):
|
def __process_data(self, ftype, ts):
|
||||||
inv_update = False
|
inv_update = False
|
||||||
msg_type = self.control >> 8
|
msg_type = self.control >> 8
|
||||||
for key, update in self.db.parse(self.ifc.read.peek(), msg_type, ftype,
|
for key, update in self.db.parse(self.ifc.rx_peek(), msg_type, ftype,
|
||||||
self.node_id):
|
self.node_id):
|
||||||
if update:
|
if update:
|
||||||
if key == 'inverter':
|
if key == 'inverter':
|
||||||
@@ -513,7 +515,7 @@ class SolarmanV5(Message):
|
|||||||
self.__forward_msg()
|
self.__forward_msg()
|
||||||
|
|
||||||
def msg_dev_ind(self):
|
def msg_dev_ind(self):
|
||||||
data = self.ifc.read.peek()[self.header_len:]
|
data = self.ifc.rx_peek()[self.header_len:]
|
||||||
result = struct.unpack_from(self.HDR_FMT, data, 0)
|
result = struct.unpack_from(self.HDR_FMT, data, 0)
|
||||||
ftype = result[0] # always 2
|
ftype = result[0] # always 2
|
||||||
total = result[1]
|
total = result[1]
|
||||||
@@ -534,7 +536,7 @@ class SolarmanV5(Message):
|
|||||||
self.__send_ack_rsp(0x1110, ftype)
|
self.__send_ack_rsp(0x1110, ftype)
|
||||||
|
|
||||||
def msg_data_ind(self):
|
def msg_data_ind(self):
|
||||||
data = self.ifc.read.peek()
|
data = self.ifc.rx_peek()
|
||||||
result = struct.unpack_from('<BHLLLHL', data, self.header_len)
|
result = struct.unpack_from('<BHLLLHL', data, self.header_len)
|
||||||
ftype = result[0] # 1 or 0x81
|
ftype = result[0] # 1 or 0x81
|
||||||
sensor = result[1]
|
sensor = result[1]
|
||||||
@@ -562,7 +564,7 @@ class SolarmanV5(Message):
|
|||||||
self.new_state_up()
|
self.new_state_up()
|
||||||
|
|
||||||
def msg_sync_start(self):
|
def msg_sync_start(self):
|
||||||
data = self.ifc.read.peek()[self.header_len:]
|
data = self.ifc.rx_peek()[self.header_len:]
|
||||||
result = struct.unpack_from(self.HDR_FMT, data, 0)
|
result = struct.unpack_from(self.HDR_FMT, data, 0)
|
||||||
ftype = result[0]
|
ftype = result[0]
|
||||||
total = result[1]
|
total = result[1]
|
||||||
@@ -575,8 +577,8 @@ class SolarmanV5(Message):
|
|||||||
self.__send_ack_rsp(0x1310, ftype)
|
self.__send_ack_rsp(0x1310, ftype)
|
||||||
|
|
||||||
def msg_command_req(self):
|
def msg_command_req(self):
|
||||||
data = self.ifc.read.peek()[self.header_len:
|
data = self.ifc.rx_peek()[self.header_len:
|
||||||
self.header_len+self.data_len]
|
self.header_len+self.data_len]
|
||||||
result = struct.unpack_from('<B', data, 0)
|
result = struct.unpack_from('<B', data, 0)
|
||||||
ftype = result[0]
|
ftype = result[0]
|
||||||
if ftype == self.AT_CMD:
|
if ftype == self.AT_CMD:
|
||||||
@@ -588,8 +590,8 @@ class SolarmanV5(Message):
|
|||||||
self.forward_at_cmd_resp = True
|
self.forward_at_cmd_resp = True
|
||||||
|
|
||||||
elif ftype == self.MB_RTU_CMD:
|
elif ftype == self.MB_RTU_CMD:
|
||||||
if self.remote_stream.mb.recv_req(data[15:],
|
if self.remote.stream.mb.recv_req(data[15:],
|
||||||
self.remote_stream.
|
self.remote.stream.
|
||||||
__forward_msg):
|
__forward_msg):
|
||||||
self.inc_counter('Modbus_Command')
|
self.inc_counter('Modbus_Command')
|
||||||
else:
|
else:
|
||||||
@@ -604,7 +606,7 @@ class SolarmanV5(Message):
|
|||||||
self.mqtt.publish(key, data))
|
self.mqtt.publish(key, data))
|
||||||
|
|
||||||
def get_cmd_rsp_log_lvl(self) -> int:
|
def get_cmd_rsp_log_lvl(self) -> int:
|
||||||
ftype = self.ifc.read.peek()[self.header_len]
|
ftype = self.ifc.rx_peek()[self.header_len]
|
||||||
if ftype == self.AT_CMD:
|
if ftype == self.AT_CMD:
|
||||||
if self.forward_at_cmd_resp:
|
if self.forward_at_cmd_resp:
|
||||||
return logging.INFO
|
return logging.INFO
|
||||||
@@ -616,8 +618,8 @@ class SolarmanV5(Message):
|
|||||||
return logging.WARNING
|
return logging.WARNING
|
||||||
|
|
||||||
def msg_command_rsp(self):
|
def msg_command_rsp(self):
|
||||||
data = self.ifc.read.peek()[self.header_len:
|
data = self.ifc.rx_peek()[self.header_len:
|
||||||
self.header_len+self.data_len]
|
self.header_len+self.data_len]
|
||||||
ftype = data[0]
|
ftype = data[0]
|
||||||
if ftype == self.AT_CMD:
|
if ftype == self.AT_CMD:
|
||||||
if not self.forward_at_cmd_resp:
|
if not self.forward_at_cmd_resp:
|
||||||
@@ -653,7 +655,7 @@ class SolarmanV5(Message):
|
|||||||
self.__build_model_name()
|
self.__build_model_name()
|
||||||
|
|
||||||
def msg_hbeat_ind(self):
|
def msg_hbeat_ind(self):
|
||||||
data = self.ifc.read.peek()[self.header_len:]
|
data = self.ifc.rx_peek()[self.header_len:]
|
||||||
result = struct.unpack_from('<B', data, 0)
|
result = struct.unpack_from('<B', data, 0)
|
||||||
ftype = result[0]
|
ftype = result[0]
|
||||||
|
|
||||||
@@ -662,7 +664,7 @@ class SolarmanV5(Message):
|
|||||||
self.new_state_up()
|
self.new_state_up()
|
||||||
|
|
||||||
def msg_sync_end(self):
|
def msg_sync_end(self):
|
||||||
data = self.ifc.read.peek()[self.header_len:]
|
data = self.ifc.rx_peek()[self.header_len:]
|
||||||
result = struct.unpack_from(self.HDR_FMT, data, 0)
|
result = struct.unpack_from(self.HDR_FMT, data, 0)
|
||||||
ftype = result[0]
|
ftype = result[0]
|
||||||
total = result[1]
|
total = result[1]
|
||||||
@@ -675,7 +677,7 @@ class SolarmanV5(Message):
|
|||||||
self.__send_ack_rsp(0x1810, ftype)
|
self.__send_ack_rsp(0x1810, ftype)
|
||||||
|
|
||||||
def msg_response(self):
|
def msg_response(self):
|
||||||
data = self.ifc.read.peek()[self.header_len:]
|
data = self.ifc.rx_peek()[self.header_len:]
|
||||||
result = struct.unpack_from('<BBLL', data, 0)
|
result = struct.unpack_from('<BBLL', data, 0)
|
||||||
ftype = result[0] # always 2
|
ftype = result[0] # always 2
|
||||||
valid = result[1] == 1 # status
|
valid = result[1] == 1 # status
|
||||||
|
|||||||
@@ -383,12 +383,14 @@ class Infos:
|
|||||||
'''inc proxy statistic counter'''
|
'''inc proxy statistic counter'''
|
||||||
db_dict = cls.stat['proxy']
|
db_dict = cls.stat['proxy']
|
||||||
db_dict[counter] += 1
|
db_dict[counter] += 1
|
||||||
|
cls.new_stat_data['proxy'] = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def dec_counter(cls, counter: str) -> None:
|
def dec_counter(cls, counter: str) -> None:
|
||||||
'''dec proxy statistic counter'''
|
'''dec proxy statistic counter'''
|
||||||
db_dict = cls.stat['proxy']
|
db_dict = cls.stat['proxy']
|
||||||
db_dict[counter] -= 1
|
db_dict[counter] -= 1
|
||||||
|
cls.new_stat_data['proxy'] = True
|
||||||
|
|
||||||
def ha_proxy_confs(self, ha_prfx: str, node_id: str, snr: str) \
|
def ha_proxy_confs(self, ha_prfx: str, node_id: str, snr: str) \
|
||||||
-> Generator[tuple[str, str, str, str], None, None]:
|
-> Generator[tuple[str, str, str, str], None, None]:
|
||||||
|
|||||||
@@ -90,6 +90,12 @@ class State(Enum):
|
|||||||
|
|
||||||
class Message(metaclass=IterRegistry):
|
class Message(metaclass=IterRegistry):
|
||||||
_registry = []
|
_registry = []
|
||||||
|
MAX_START_TIME = 400
|
||||||
|
'''maximum time without a received msg in sec'''
|
||||||
|
MAX_INV_IDLE_TIME = 120
|
||||||
|
'''maximum time without a received msg from the inverter in sec'''
|
||||||
|
MAX_DEF_IDLE_TIME = 360
|
||||||
|
'''maximum default time without a received msg in sec'''
|
||||||
|
|
||||||
def __init__(self, server_side: bool, send_modbus_cb:
|
def __init__(self, server_side: bool, send_modbus_cb:
|
||||||
Callable[[bytes, int, str], None], mb_timeout: int):
|
Callable[[bytes, int, str], None], mb_timeout: int):
|
||||||
@@ -105,12 +111,21 @@ class Message(metaclass=IterRegistry):
|
|||||||
self.header_len = 0
|
self.header_len = 0
|
||||||
self.data_len = 0
|
self.data_len = 0
|
||||||
self.unique_id = 0
|
self.unique_id = 0
|
||||||
self.node_id = '' # will be overwritten in the child class's __init__
|
self._node_id = ''
|
||||||
self.sug_area = ''
|
self.sug_area = ''
|
||||||
self.new_data = {}
|
self.new_data = {}
|
||||||
self.state = State.init
|
self.state = State.init
|
||||||
self.shutdown_started = False
|
self.shutdown_started = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def node_id(self):
|
||||||
|
return self._node_id
|
||||||
|
|
||||||
|
@node_id.setter
|
||||||
|
def node_id(self, value):
|
||||||
|
self._node_id = value
|
||||||
|
self.ifc.set_node_id(value)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Empty methods, that have to be implemented in any child class which
|
Empty methods, that have to be implemented in any child class which
|
||||||
don't use asyncio
|
don't use asyncio
|
||||||
@@ -138,6 +153,16 @@ class Message(metaclass=IterRegistry):
|
|||||||
# logger.info(f'update: key: {key} ts:{tstr}'
|
# logger.info(f'update: key: {key} ts:{tstr}'
|
||||||
self.db.set_db_def_value(info_id, round(ts))
|
self.db.set_db_def_value(info_id, round(ts))
|
||||||
|
|
||||||
|
def _timeout(self) -> int:
|
||||||
|
if self.state == State.init or self.state == State.received:
|
||||||
|
to = self.MAX_START_TIME
|
||||||
|
elif self.state == State.up and \
|
||||||
|
self.server_side and self.modbus_polling:
|
||||||
|
to = self.MAX_INV_IDLE_TIME
|
||||||
|
else:
|
||||||
|
to = self.MAX_DEF_IDLE_TIME
|
||||||
|
return to
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Our puplic methods
|
Our puplic methods
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import asyncio
|
|||||||
if __name__ == "app.src.modbus_tcp":
|
if __name__ == "app.src.modbus_tcp":
|
||||||
from app.src.config import Config
|
from app.src.config import Config
|
||||||
from app.src.gen3plus.inverter_g3p import InverterG3P
|
from app.src.gen3plus.inverter_g3p import InverterG3P
|
||||||
|
from app.src.infos import Infos
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
from config import Config
|
from config import Config
|
||||||
from gen3plus.inverter_g3p import InverterG3P
|
from gen3plus.inverter_g3p import InverterG3P
|
||||||
|
from infos import Infos
|
||||||
|
|
||||||
logger = logging.getLogger('conn')
|
logger = logging.getLogger('conn')
|
||||||
|
|
||||||
@@ -27,13 +29,14 @@ class ModbusConn():
|
|||||||
client_mode=True)
|
client_mode=True)
|
||||||
logging.info(f'[{self.stream.node_id}:{self.stream.conn_no}] '
|
logging.info(f'[{self.stream.node_id}:{self.stream.conn_no}] '
|
||||||
f'Connected to {self.addr}')
|
f'Connected to {self.addr}')
|
||||||
self.stream.inc_counter('Inverter_Cnt')
|
Infos.inc_counter('Inverter_Cnt')
|
||||||
await self.stream.publish_outstanding_mqtt()
|
await self.stream._ifc.publish_outstanding_mqtt()
|
||||||
return self.stream
|
return self.stream
|
||||||
|
|
||||||
async def __aexit__(self, exc_type, exc, tb):
|
async def __aexit__(self, exc_type, exc, tb):
|
||||||
self.stream.dec_counter('Inverter_Cnt')
|
Infos.dec_counter('Inverter_Cnt')
|
||||||
await self.stream.publish_outstanding_mqtt()
|
await self.stream._ifc.publish_outstanding_mqtt()
|
||||||
|
self.stream.close()
|
||||||
|
|
||||||
|
|
||||||
class ModbusTcp():
|
class ModbusTcp():
|
||||||
@@ -60,7 +63,7 @@ class ModbusTcp():
|
|||||||
try:
|
try:
|
||||||
async with ModbusConn(host, port) as stream:
|
async with ModbusConn(host, port) as stream:
|
||||||
await stream.send_start_cmd(snr, host)
|
await stream.send_start_cmd(snr, host)
|
||||||
await stream.loop()
|
await stream._ifc.loop()
|
||||||
logger.info(f'[{stream.node_id}:{stream.conn_no}] '
|
logger.info(f'[{stream.node_id}:{stream.conn_no}] '
|
||||||
f'Connection closed - Shutdown: '
|
f'Connection closed - Shutdown: '
|
||||||
f'{stream.shutdown_started}')
|
f'{stream.shutdown_started}')
|
||||||
|
|||||||
@@ -74,14 +74,14 @@ async def handle_client(reader: StreamReader, writer: StreamWriter):
|
|||||||
'''Handles a new incoming connection and starts an async loop'''
|
'''Handles a new incoming connection and starts an async loop'''
|
||||||
|
|
||||||
addr = writer.get_extra_info('peername')
|
addr = writer.get_extra_info('peername')
|
||||||
await InverterG3(reader, writer, addr).server_loop(addr)
|
await InverterG3(reader, writer, addr)._ifc.server_loop(addr)
|
||||||
|
|
||||||
|
|
||||||
async def handle_client_v2(reader: StreamReader, writer: StreamWriter):
|
async def handle_client_v2(reader: StreamReader, writer: StreamWriter):
|
||||||
'''Handles a new incoming connection and starts an async loop'''
|
'''Handles a new incoming connection and starts an async loop'''
|
||||||
|
|
||||||
addr = writer.get_extra_info('peername')
|
addr = writer.get_extra_info('peername')
|
||||||
await InverterG3P(reader, writer, addr).server_loop(addr)
|
await InverterG3P(reader, writer, addr)._ifc.server_loop(addr)
|
||||||
|
|
||||||
|
|
||||||
async def handle_shutdown(web_task):
|
async def handle_shutdown(web_task):
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
from itertools import count
|
||||||
from mock import patch
|
from mock import patch
|
||||||
from app.src.async_stream import AsyncStream
|
from app.src.async_stream import AsyncStream, AsyncIfcImpl
|
||||||
from app.src.gen3.connection_g3 import ConnectionG3
|
from app.src.gen3.connection_g3 import ConnectionG3
|
||||||
from app.src.gen3.talent import Talent
|
from app.src.gen3.talent import Talent
|
||||||
|
|
||||||
@@ -60,19 +61,19 @@ class FakeWriter():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_method_calls(patch_async_init, patch_talent_init, patch_healthy, patch_async_close, patch_talent_close):
|
def test_method_calls(patch_talent_init, patch_healthy, patch_async_close, patch_talent_close):
|
||||||
spy1 = patch_async_init
|
AsyncIfcImpl._ids = count(5)
|
||||||
spy2 = patch_talent_init
|
spy2 = patch_talent_init
|
||||||
spy3 = patch_healthy
|
spy3 = patch_healthy
|
||||||
spy4 = patch_async_close
|
spy4 = patch_async_close
|
||||||
spy5 = patch_talent_close
|
spy5 = patch_talent_close
|
||||||
reader = FakeReader()
|
reader = FakeReader()
|
||||||
writer = FakeWriter()
|
writer = FakeWriter()
|
||||||
id_str = "id_string"
|
id_str = "id_string"
|
||||||
addr = ('proxy.local', 10000)
|
addr = ('proxy.local', 10000)
|
||||||
conn = ConnectionG3(reader, writer, addr,
|
conn = ConnectionG3(reader, writer, addr,
|
||||||
remote_stream= None, server_side=True, id_str=id_str)
|
rstream= None, server_side=True, id_str=id_str)
|
||||||
spy1.assert_called_once_with(conn, reader, writer, addr, conn._ifc)
|
assert 5 == conn._ifc.get_conn_no()
|
||||||
spy2.assert_called_once_with(conn, True, conn._ifc, id_str)
|
spy2.assert_called_once_with(conn, True, conn._ifc, id_str)
|
||||||
conn.healthy()
|
conn.healthy()
|
||||||
|
|
||||||
@@ -81,4 +82,3 @@ def test_method_calls(patch_async_init, patch_talent_init, patch_healthy, patch_
|
|||||||
conn.close()
|
conn.close()
|
||||||
spy4.assert_called_once()
|
spy4.assert_called_once()
|
||||||
spy5.assert_called_once()
|
spy5.assert_called_once()
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,16 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
from itertools import count
|
||||||
from mock import patch
|
from mock import patch
|
||||||
from app.src.singleton import Singleton
|
from app.src.singleton import Singleton
|
||||||
from app.src.async_stream import AsyncStream
|
from app.src.async_stream import AsyncStream, AsyncIfcImpl
|
||||||
from app.src.gen3plus.connection_g3p import ConnectionG3P
|
from app.src.gen3plus.connection_g3p import ConnectionG3P
|
||||||
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def patch_async_init():
|
def patch_async_init():
|
||||||
with patch.object(AsyncStream, '__init__') as conn:
|
with patch.object(AsyncStream, '__init__', return_value= None) as conn:
|
||||||
yield conn
|
yield conn
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -66,18 +67,18 @@ class FakeWriter():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_method_calls(patch_async_init, patch_solarman_init, patch_healthy, patch_async_close, patch_solarman_close):
|
def test_method_calls(patch_solarman_init, patch_healthy, patch_async_close, patch_solarman_close):
|
||||||
spy1 = patch_async_init
|
AsyncIfcImpl._ids = count(5)
|
||||||
spy2 = patch_solarman_init
|
spy2 = patch_solarman_init
|
||||||
spy3 = patch_healthy
|
spy3 = patch_healthy
|
||||||
spy4 = patch_async_close
|
spy4 = patch_async_close
|
||||||
spy5 = patch_solarman_close
|
spy5 = patch_solarman_close
|
||||||
reader = FakeReader()
|
reader = FakeReader()
|
||||||
writer = FakeWriter()
|
writer = FakeWriter()
|
||||||
addr = ('proxy.local', 10000)
|
addr = ('proxy.local', 10000)
|
||||||
conn = ConnectionG3P(reader, writer, addr,
|
conn = ConnectionG3P(reader, writer, addr,
|
||||||
remote_stream= None, server_side=True, client_mode=False)
|
rstream= None, server_side=True, client_mode=False)
|
||||||
spy1.assert_called_once_with(conn, reader, writer, addr, conn._ifc)
|
assert 5 == conn._ifc.get_conn_no()
|
||||||
spy2.assert_called_once_with(conn, True, False, conn._ifc)
|
spy2.assert_called_once_with(conn, True, False, conn._ifc)
|
||||||
conn.healthy()
|
conn.healthy()
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pytest_plugins = ('pytest_asyncio',)
|
|||||||
@pytest.fixture(scope="module", autouse=True)
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
def module_init():
|
def module_init():
|
||||||
def new_init(cls, cb_mqtt_is_up):
|
def new_init(cls, cb_mqtt_is_up):
|
||||||
cb_mqtt_is_up()
|
pass # empty test methos
|
||||||
|
|
||||||
Singleton._instances.clear()
|
Singleton._instances.clear()
|
||||||
with patch.object(Mqtt, '__init__', new_init):
|
with patch.object(Mqtt, '__init__', new_init):
|
||||||
@@ -69,6 +69,7 @@ async def test_inverter_cb(config_conn):
|
|||||||
assert 'homeassistant/' == Inverter.discovery_prfx
|
assert 'homeassistant/' == Inverter.discovery_prfx
|
||||||
assert 'tsun/' == Inverter.entity_prfx
|
assert 'tsun/' == Inverter.entity_prfx
|
||||||
assert 'test_1/' == Inverter.proxy_node_id
|
assert 'test_1/' == Inverter.proxy_node_id
|
||||||
|
await Inverter._cb_mqtt_is_up()
|
||||||
spy.assert_called_once()
|
spy.assert_called_once()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ async def test_remote_conn(config_conn, patch_open_connection, patch_conn_close)
|
|||||||
|
|
||||||
await inverter.async_create_remote()
|
await inverter.async_create_remote()
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
assert inverter.remote_stream
|
assert inverter.remote.stream
|
||||||
inverter.close()
|
inverter.close()
|
||||||
spy1.assert_called_once()
|
spy1.assert_called_once()
|
||||||
|
|
||||||
@@ -151,12 +151,12 @@ async def test_remote_except(config_conn, patch_open_connection, patch_conn_clos
|
|||||||
|
|
||||||
await inverter.async_create_remote()
|
await inverter.async_create_remote()
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
assert inverter.remote_stream==None
|
assert inverter.remote.stream==None
|
||||||
|
|
||||||
test = TestType.RD_TEST_EXCEPT
|
test = TestType.RD_TEST_EXCEPT
|
||||||
await inverter.async_create_remote()
|
await inverter.async_create_remote()
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
assert inverter.remote_stream==None
|
assert inverter.remote.stream==None
|
||||||
inverter.close()
|
inverter.close()
|
||||||
spy1.assert_called_once()
|
spy1.assert_called_once()
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ async def test_remote_conn(config_conn, patch_open_connection, patch_conn_close)
|
|||||||
|
|
||||||
await inverter.async_create_remote()
|
await inverter.async_create_remote()
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
assert inverter.remote_stream
|
assert inverter.remote.stream
|
||||||
inverter.close()
|
inverter.close()
|
||||||
spy1.assert_called_once()
|
spy1.assert_called_once()
|
||||||
|
|
||||||
@@ -152,12 +152,12 @@ async def test_remote_except(config_conn, patch_open_connection, patch_conn_clos
|
|||||||
|
|
||||||
await inverter.async_create_remote()
|
await inverter.async_create_remote()
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
assert inverter.remote_stream==None
|
assert inverter.remote.stream==None
|
||||||
|
|
||||||
test = TestType.RD_TEST_EXCEPT
|
test = TestType.RD_TEST_EXCEPT
|
||||||
await inverter.async_create_remote()
|
await inverter.async_create_remote()
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
assert inverter.remote_stream==None
|
assert inverter.remote.stream==None
|
||||||
inverter.close()
|
inverter.close()
|
||||||
spy1.assert_called_once()
|
spy1.assert_called_once()
|
||||||
|
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ async def test_modbus_conn(patch_open):
|
|||||||
async with ModbusConn('test.local', 1234) as stream:
|
async with ModbusConn('test.local', 1234) as stream:
|
||||||
assert stream.node_id == 'G3P'
|
assert stream.node_id == 'G3P'
|
||||||
assert stream.addr == ('test.local', 1234)
|
assert stream.addr == ('test.local', 1234)
|
||||||
assert type(stream._reader) is FakeReader
|
assert type(stream._ifc._reader) is FakeReader
|
||||||
assert type(stream._writer) is FakeWriter
|
assert type(stream._ifc._writer) is FakeWriter
|
||||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 1
|
assert Infos.stat['proxy']['Inverter_Cnt'] == 1
|
||||||
|
|
||||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
assert Infos.stat['proxy']['Inverter_Cnt'] == 0
|
||||||
@@ -209,7 +209,7 @@ async def test_modbus_cnf2(config_conn, patch_no_mqtt, patch_open):
|
|||||||
test += 1
|
test += 1
|
||||||
assert Infos.stat['proxy']['Inverter_Cnt'] == 1
|
assert Infos.stat['proxy']['Inverter_Cnt'] == 1
|
||||||
m.shutdown_started = True
|
m.shutdown_started = True
|
||||||
m._reader.on_recv.set()
|
m._ifc._reader.on_recv.set()
|
||||||
del m
|
del m
|
||||||
|
|
||||||
assert 1 == test
|
assert 1 == test
|
||||||
@@ -236,13 +236,13 @@ async def test_modbus_cnf3(config_conn, patch_no_mqtt, patch_open):
|
|||||||
test += 1
|
test += 1
|
||||||
if test == 1:
|
if test == 1:
|
||||||
m.shutdown_started = False
|
m.shutdown_started = False
|
||||||
m._reader.on_recv.set()
|
m.ifc._reader.on_recv.set()
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
assert m.state == State.closed
|
assert m.state == State.closed
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
else:
|
else:
|
||||||
m.shutdown_started = True
|
m.shutdown_started = True
|
||||||
m._reader.on_recv.set()
|
m.ifc._reader.on_recv.set()
|
||||||
del m
|
del m
|
||||||
|
|
||||||
assert 2 == test
|
assert 2 == test
|
||||||
@@ -269,13 +269,14 @@ async def test_mqtt_err(config_conn, patch_mqtt_err, patch_open):
|
|||||||
test += 1
|
test += 1
|
||||||
if test == 1:
|
if test == 1:
|
||||||
m.shutdown_started = False
|
m.shutdown_started = False
|
||||||
m._reader.on_recv.set()
|
m._ifc._reader.on_recv.set()
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
assert m.state == State.closed
|
assert m.state == State.closed
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
else:
|
else:
|
||||||
m.shutdown_started = True
|
m.shutdown_started = True
|
||||||
m._reader.on_recv.set()
|
m._ifc._reader.on_recv.set()
|
||||||
del m
|
del m
|
||||||
|
|
||||||
await asyncio.sleep(0.01)
|
await asyncio.sleep(0.01)
|
||||||
@@ -301,13 +302,13 @@ async def test_mqtt_except(config_conn, patch_mqtt_except, patch_open):
|
|||||||
test += 1
|
test += 1
|
||||||
if test == 1:
|
if test == 1:
|
||||||
m.shutdown_started = False
|
m.shutdown_started = False
|
||||||
m._reader.on_recv.set()
|
m._ifc._reader.on_recv.set()
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
assert m.state == State.closed
|
assert m.state == State.closed
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
else:
|
else:
|
||||||
m.shutdown_started = True
|
m.shutdown_started = True
|
||||||
m._reader.on_recv.set()
|
m._ifc._reader.on_recv.set()
|
||||||
del m
|
del m
|
||||||
|
|
||||||
await asyncio.sleep(0.01)
|
await asyncio.sleep(0.01)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import aiomqtt
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from mock import patch, Mock
|
from mock import patch, Mock
|
||||||
from app.src.async_ifc import AsyncIfc
|
from app.src.async_stream import AsyncIfcImpl
|
||||||
from app.src.singleton import Singleton
|
from app.src.singleton import Singleton
|
||||||
from app.src.mqtt import Mqtt
|
from app.src.mqtt import Mqtt
|
||||||
from app.src.modbus import Modbus
|
from app.src.modbus import Modbus
|
||||||
@@ -45,8 +45,7 @@ def config_no_conn(test_port):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def spy_at_cmd():
|
def spy_at_cmd():
|
||||||
ifc = AsyncIfc()
|
conn = SolarmanV5(server_side=True, client_mode= False, ifc=AsyncIfcImpl())
|
||||||
conn = SolarmanV5(server_side=True, client_mode= False, ifc=ifc)
|
|
||||||
conn.node_id = 'inv_2/'
|
conn.node_id = 'inv_2/'
|
||||||
with patch.object(conn, 'send_at_cmd', wraps=conn.send_at_cmd) as wrapped_conn:
|
with patch.object(conn, 'send_at_cmd', wraps=conn.send_at_cmd) as wrapped_conn:
|
||||||
yield wrapped_conn
|
yield wrapped_conn
|
||||||
@@ -54,8 +53,7 @@ def spy_at_cmd():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def spy_modbus_cmd():
|
def spy_modbus_cmd():
|
||||||
ifc = AsyncIfc()
|
conn = SolarmanV5(server_side=True, client_mode= False, ifc=AsyncIfcImpl())
|
||||||
conn = SolarmanV5(server_side=True, client_mode= False, ifc=ifc)
|
|
||||||
conn.node_id = 'inv_1/'
|
conn.node_id = 'inv_1/'
|
||||||
with patch.object(conn, 'send_modbus_cmd', wraps=conn.send_modbus_cmd) as wrapped_conn:
|
with patch.object(conn, 'send_modbus_cmd', wraps=conn.send_modbus_cmd) as wrapped_conn:
|
||||||
yield wrapped_conn
|
yield wrapped_conn
|
||||||
@@ -63,8 +61,7 @@ def spy_modbus_cmd():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def spy_modbus_cmd_client():
|
def spy_modbus_cmd_client():
|
||||||
ifc = AsyncIfc()
|
conn = SolarmanV5(server_side=False, client_mode= False, ifc=AsyncIfcImpl())
|
||||||
conn = SolarmanV5(server_side=False, client_mode= False, ifc=ifc)
|
|
||||||
conn.node_id = 'inv_1/'
|
conn.node_id = 'inv_1/'
|
||||||
with patch.object(conn, 'send_modbus_cmd', wraps=conn.send_modbus_cmd) as wrapped_conn:
|
with patch.object(conn, 'send_modbus_cmd', wraps=conn.send_modbus_cmd) as wrapped_conn:
|
||||||
yield wrapped_conn
|
yield wrapped_conn
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
from math import isclose
|
from math import isclose
|
||||||
from app.src.async_ifc import AsyncIfc
|
from app.src.async_stream import AsyncIfcImpl, StreamPtr
|
||||||
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
from app.src.gen3plus.solarman_v5 import SolarmanV5
|
||||||
from app.src.config import Config
|
from app.src.config import Config
|
||||||
from app.src.infos import Infos, Register
|
from app.src.infos import Infos, Register
|
||||||
@@ -34,14 +34,15 @@ class Mqtt():
|
|||||||
|
|
||||||
class MemoryStream(SolarmanV5):
|
class MemoryStream(SolarmanV5):
|
||||||
def __init__(self, msg, chunks = (0,), server_side: bool = True):
|
def __init__(self, msg, chunks = (0,), server_side: bool = True):
|
||||||
_ifc = AsyncIfc()
|
_ifc = AsyncIfcImpl()
|
||||||
super().__init__(server_side, client_mode=False, ifc=_ifc)
|
super().__init__(server_side, client_mode=False, ifc=_ifc)
|
||||||
if server_side:
|
if server_side:
|
||||||
self.mb.timeout = 0.4 # overwrite for faster testing
|
self.mb.timeout = 0.4 # overwrite for faster testing
|
||||||
|
self.remote = StreamPtr(None)
|
||||||
self.mb_first_timeout = 0.5
|
self.mb_first_timeout = 0.5
|
||||||
self.mb_timeout = 0.5
|
self.mb_timeout = 0.5
|
||||||
self.sent_pdu = b''
|
self.sent_pdu = b''
|
||||||
self.ifc.write.reg_trigger(self.write_cb)
|
self.ifc.tx_fifo.reg_trigger(self.write_cb)
|
||||||
self.mqtt = Mqtt()
|
self.mqtt = Mqtt()
|
||||||
self.__msg = msg
|
self.__msg = msg
|
||||||
self.__msg_len = len(msg)
|
self.__msg_len = len(msg)
|
||||||
@@ -63,7 +64,7 @@ class MemoryStream(SolarmanV5):
|
|||||||
def write_cb(self):
|
def write_cb(self):
|
||||||
if self.test_exception_async_write:
|
if self.test_exception_async_write:
|
||||||
raise RuntimeError("Peer closed.")
|
raise RuntimeError("Peer closed.")
|
||||||
self.sent_pdu = self.ifc.write.get()
|
self.sent_pdu = self.ifc.tx_fifo.get()
|
||||||
|
|
||||||
def _timestamp(self):
|
def _timestamp(self):
|
||||||
return timestamp
|
return timestamp
|
||||||
@@ -87,11 +88,11 @@ class MemoryStream(SolarmanV5):
|
|||||||
chunk_len = self.__chunks[self.__chunk_idx]
|
chunk_len = self.__chunks[self.__chunk_idx]
|
||||||
self.__chunk_idx += 1
|
self.__chunk_idx += 1
|
||||||
if chunk_len!=0:
|
if chunk_len!=0:
|
||||||
self.ifc.read += self.__msg[self.__offs:chunk_len]
|
self.ifc.rx_fifo += self.__msg[self.__offs:chunk_len]
|
||||||
copied_bytes = chunk_len - self.__offs
|
copied_bytes = chunk_len - self.__offs
|
||||||
self.__offs = chunk_len
|
self.__offs = chunk_len
|
||||||
else:
|
else:
|
||||||
self.ifc.read += self.__msg[self.__offs:]
|
self.ifc.rx_fifo += self.__msg[self.__offs:]
|
||||||
copied_bytes = self.__msg_len - self.__offs
|
copied_bytes = self.__msg_len - self.__offs
|
||||||
self.__offs = self.__msg_len
|
self.__offs = self.__msg_len
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -100,8 +101,8 @@ class MemoryStream(SolarmanV5):
|
|||||||
|
|
||||||
def createClientStream(self, msg, chunks = (0,)):
|
def createClientStream(self, msg, chunks = (0,)):
|
||||||
c = MemoryStream(msg, chunks, False)
|
c = MemoryStream(msg, chunks, False)
|
||||||
self.remote_stream = c
|
self.remote.stream = c
|
||||||
c. remote_stream = self
|
c. remote.stream = self
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def _SolarmanV5__flush_recv_msg(self) -> None:
|
def _SolarmanV5__flush_recv_msg(self) -> None:
|
||||||
@@ -687,9 +688,9 @@ def test_read_message(device_ind_msg):
|
|||||||
assert m.control == 0x4110
|
assert m.control == 0x4110
|
||||||
assert str(m.seq) == '01:00'
|
assert str(m.seq) == '01:00'
|
||||||
assert m.data_len == 0xd4
|
assert m.data_len == 0xd4
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -708,9 +709,9 @@ def test_invalid_start_byte(invalid_start_byte, device_ind_msg):
|
|||||||
assert m.control == 0x4110
|
assert m.control == 0x4110
|
||||||
assert str(m.seq) == '01:00'
|
assert str(m.seq) == '01:00'
|
||||||
assert m.data_len == 0xd4
|
assert m.data_len == 0xd4
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -728,9 +729,9 @@ def test_invalid_stop_byte(invalid_stop_byte):
|
|||||||
assert m.control == 0x4110
|
assert m.control == 0x4110
|
||||||
assert str(m.seq) == '01:00'
|
assert str(m.seq) == '01:00'
|
||||||
assert m.data_len == 0xd4
|
assert m.data_len == 0xd4
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -753,9 +754,9 @@ def test_invalid_stop_byte2(invalid_stop_byte, device_ind_msg):
|
|||||||
assert m.msg_recvd[1]['data_len']==0xd4
|
assert m.msg_recvd[1]['data_len']==0xd4
|
||||||
|
|
||||||
assert m.unique_id == None
|
assert m.unique_id == None
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -775,9 +776,9 @@ def test_invalid_stop_start_byte(invalid_stop_byte, invalid_start_byte):
|
|||||||
assert m.control == 0x4110
|
assert m.control == 0x4110
|
||||||
assert str(m.seq) == '01:00'
|
assert str(m.seq) == '01:00'
|
||||||
assert m.data_len == 0xd4
|
assert m.data_len == 0xd4
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -799,9 +800,9 @@ def test_invalid_checksum(invalid_checksum, device_ind_msg):
|
|||||||
assert m.msg_recvd[1]['control']==0x4110
|
assert m.msg_recvd[1]['control']==0x4110
|
||||||
assert m.msg_recvd[1]['seq']=='01:00'
|
assert m.msg_recvd[1]['seq']=='01:00'
|
||||||
assert m.msg_recvd[1]['data_len']==0xd4
|
assert m.msg_recvd[1]['data_len']==0xd4
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -821,8 +822,8 @@ def test_read_message_twice(config_no_tsun_inv1, device_ind_msg, device_rsp_msg)
|
|||||||
assert m.msg_recvd[1]['control']==0x4110
|
assert m.msg_recvd[1]['control']==0x4110
|
||||||
assert m.msg_recvd[1]['seq']=='01:01'
|
assert m.msg_recvd[1]['seq']=='01:01'
|
||||||
assert m.msg_recvd[1]['data_len']==0xd4
|
assert m.msg_recvd[1]['data_len']==0xd4
|
||||||
assert m.ifc.write.get()==device_rsp_msg+device_rsp_msg
|
assert m.ifc.tx_fifo.get()==device_rsp_msg+device_rsp_msg
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -893,11 +894,11 @@ def test_read_two_messages(config_tsun_allow_all, device_ind_msg, device_rsp_msg
|
|||||||
assert m.msg_recvd[1]['data_len']==0x199
|
assert m.msg_recvd[1]['data_len']==0x199
|
||||||
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
||||||
assert 0x02b0 == m.sensor_list
|
assert 0x02b0 == m.sensor_list
|
||||||
assert m.ifc.forward.get()==device_ind_msg+inverter_ind_msg
|
assert m.ifc.fwd_fifo.get()==device_ind_msg+inverter_ind_msg
|
||||||
assert m.ifc.write.get()==device_rsp_msg+inverter_rsp_msg
|
assert m.ifc.tx_fifo.get()==device_rsp_msg+inverter_rsp_msg
|
||||||
|
|
||||||
m._init_new_client_conn()
|
m._init_new_client_conn()
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_read_two_messages2(config_tsun_allow_all, inverter_ind_msg, inverter_ind_msg_81, inverter_rsp_msg, inverter_rsp_msg_81):
|
def test_read_two_messages2(config_tsun_allow_all, inverter_ind_msg, inverter_ind_msg_81, inverter_rsp_msg, inverter_rsp_msg_81):
|
||||||
@@ -918,11 +919,11 @@ def test_read_two_messages2(config_tsun_allow_all, inverter_ind_msg, inverter_in
|
|||||||
assert m.msg_recvd[1]['seq']=='03:03'
|
assert m.msg_recvd[1]['seq']=='03:03'
|
||||||
assert m.msg_recvd[1]['data_len']==0x199
|
assert m.msg_recvd[1]['data_len']==0x199
|
||||||
assert m.time_ofs == 0x33e447a0
|
assert m.time_ofs == 0x33e447a0
|
||||||
assert m.ifc.forward.get()==inverter_ind_msg+inverter_ind_msg_81
|
assert m.ifc.fwd_fifo.get()==inverter_ind_msg+inverter_ind_msg_81
|
||||||
assert m.ifc.write.get()==inverter_rsp_msg+inverter_rsp_msg_81
|
assert m.ifc.tx_fifo.get()==inverter_rsp_msg+inverter_rsp_msg_81
|
||||||
|
|
||||||
m._init_new_client_conn()
|
m._init_new_client_conn()
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_read_two_messages3(config_tsun_allow_all, device_ind_msg2, device_rsp_msg2, inverter_ind_msg, inverter_rsp_msg):
|
def test_read_two_messages3(config_tsun_allow_all, device_ind_msg2, device_rsp_msg2, inverter_ind_msg, inverter_rsp_msg):
|
||||||
@@ -947,11 +948,11 @@ def test_read_two_messages3(config_tsun_allow_all, device_ind_msg2, device_rsp_m
|
|||||||
assert m.msg_recvd[1]['data_len']==0xd4
|
assert m.msg_recvd[1]['data_len']==0xd4
|
||||||
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
||||||
assert 0x02b0 == m.sensor_list
|
assert 0x02b0 == m.sensor_list
|
||||||
assert m.ifc.forward.get()==inverter_ind_msg+device_ind_msg2
|
assert m.ifc.fwd_fifo.get()==inverter_ind_msg+device_ind_msg2
|
||||||
assert m.ifc.write.get()==inverter_rsp_msg+device_rsp_msg2
|
assert m.ifc.tx_fifo.get()==inverter_rsp_msg+device_rsp_msg2
|
||||||
|
|
||||||
m._init_new_client_conn()
|
m._init_new_client_conn()
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_unkown_frame_code(config_tsun_inv1, inverter_ind_msg_81, inverter_rsp_msg_81):
|
def test_unkown_frame_code(config_tsun_inv1, inverter_ind_msg_81, inverter_rsp_msg_81):
|
||||||
@@ -966,9 +967,9 @@ def test_unkown_frame_code(config_tsun_inv1, inverter_ind_msg_81, inverter_rsp_m
|
|||||||
assert m.control == 0x4210
|
assert m.control == 0x4210
|
||||||
assert str(m.seq) == '03:03'
|
assert str(m.seq) == '03:03'
|
||||||
assert m.data_len == 0x199
|
assert m.data_len == 0x199
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==inverter_rsp_msg_81
|
assert m.ifc.tx_fifo.get()==inverter_rsp_msg_81
|
||||||
assert m.ifc.forward.get()==inverter_ind_msg_81
|
assert m.ifc.fwd_fifo.get()==inverter_ind_msg_81
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -984,9 +985,9 @@ def test_unkown_message(config_tsun_inv1, unknown_msg):
|
|||||||
assert m.control == 0x5110
|
assert m.control == 0x5110
|
||||||
assert str(m.seq) == '84:10'
|
assert str(m.seq) == '84:10'
|
||||||
assert m.data_len == 0x0a
|
assert m.data_len == 0x0a
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==unknown_msg
|
assert m.ifc.fwd_fifo.get()==unknown_msg
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1002,9 +1003,9 @@ def test_device_rsp(config_tsun_inv1, device_rsp_msg):
|
|||||||
assert m.control == 0x1110
|
assert m.control == 0x1110
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert m.data_len == 0x0a
|
assert m.data_len == 0x0a
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1020,9 +1021,9 @@ def test_inverter_rsp(config_tsun_inv1, inverter_rsp_msg):
|
|||||||
assert m.control == 0x1210
|
assert m.control == 0x1210
|
||||||
assert str(m.seq) == '02:02'
|
assert str(m.seq) == '02:02'
|
||||||
assert m.data_len == 0x0a
|
assert m.data_len == 0x0a
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1037,9 +1038,9 @@ def test_heartbeat_ind(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp_msg):
|
|||||||
assert m.control == 0x4710
|
assert m.control == 0x4710
|
||||||
assert str(m.seq) == '84:11' # value after sending response
|
assert str(m.seq) == '84:11' # value after sending response
|
||||||
assert m.data_len == 0x01
|
assert m.data_len == 0x01
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==heartbeat_rsp_msg
|
assert m.ifc.tx_fifo.get()==heartbeat_rsp_msg
|
||||||
assert m.ifc.forward.get()==heartbeat_ind_msg
|
assert m.ifc.fwd_fifo.get()==heartbeat_ind_msg
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1055,9 +1056,9 @@ def test_heartbeat_ind2(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp_msg):
|
|||||||
assert m.control == 0x4710
|
assert m.control == 0x4710
|
||||||
assert str(m.seq) == '84:11' # value after sending response
|
assert str(m.seq) == '84:11' # value after sending response
|
||||||
assert m.data_len == 0x01
|
assert m.data_len == 0x01
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==heartbeat_rsp_msg
|
assert m.ifc.tx_fifo.get()==heartbeat_rsp_msg
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1073,9 +1074,9 @@ def test_heartbeat_rsp(config_tsun_inv1, heartbeat_rsp_msg):
|
|||||||
assert m.control == 0x1710
|
assert m.control == 0x1710
|
||||||
assert str(m.seq) == '11:84' # value after sending response
|
assert str(m.seq) == '11:84' # value after sending response
|
||||||
assert m.data_len == 0x0a
|
assert m.data_len == 0x0a
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1090,15 +1091,15 @@ def test_sync_start_ind(config_tsun_inv1, sync_start_ind_msg, sync_start_rsp_msg
|
|||||||
assert m.control == 0x4310
|
assert m.control == 0x4310
|
||||||
assert str(m.seq) == '0d:0d' # value after sending response
|
assert str(m.seq) == '0d:0d' # value after sending response
|
||||||
assert m.data_len == 47
|
assert m.data_len == 47
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==sync_start_rsp_msg
|
assert m.ifc.tx_fifo.get()==sync_start_rsp_msg
|
||||||
assert m.ifc.forward.peek()==sync_start_ind_msg
|
assert m.ifc.fwd_fifo.peek()==sync_start_ind_msg
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
|
|
||||||
m.seq.server_side = False # simulate forawding to TSUN cloud
|
m.seq.server_side = False # simulate forawding to TSUN cloud
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert str(m.seq) == '0d:0e' # value after forwarding indication
|
assert str(m.seq) == '0d:0e' # value after forwarding indication
|
||||||
assert m.ifc.forward.get()==sync_start_fwd_msg
|
assert m.ifc.fwd_fifo.get()==sync_start_fwd_msg
|
||||||
|
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1114,9 +1115,9 @@ def test_sync_start_rsp(config_tsun_inv1, sync_start_rsp_msg):
|
|||||||
assert m.control == 0x1310
|
assert m.control == 0x1310
|
||||||
assert str(m.seq) == '0d:0d' # value after sending response
|
assert str(m.seq) == '0d:0d' # value after sending response
|
||||||
assert m.data_len == 0x0a
|
assert m.data_len == 0x0a
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1131,9 +1132,9 @@ def test_sync_end_ind(config_tsun_inv1, sync_end_ind_msg, sync_end_rsp_msg):
|
|||||||
assert m.control == 0x4810
|
assert m.control == 0x4810
|
||||||
assert str(m.seq) == '07:07' # value after sending response
|
assert str(m.seq) == '07:07' # value after sending response
|
||||||
assert m.data_len == 60
|
assert m.data_len == 60
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==sync_end_rsp_msg
|
assert m.ifc.tx_fifo.get()==sync_end_rsp_msg
|
||||||
assert m.ifc.forward.get()==sync_end_ind_msg
|
assert m.ifc.fwd_fifo.get()==sync_end_ind_msg
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1149,9 +1150,9 @@ def test_sync_end_rsp(config_tsun_inv1, sync_end_rsp_msg):
|
|||||||
assert m.control == 0x1810
|
assert m.control == 0x1810
|
||||||
assert str(m.seq) == '07:07' # value after sending response
|
assert str(m.seq) == '07:07' # value after sending response
|
||||||
assert m.data_len == 0x0a
|
assert m.data_len == 0x0a
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1169,9 +1170,9 @@ def test_build_modell_600(config_tsun_allow_all, inverter_ind_msg):
|
|||||||
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
assert '02b0' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
||||||
assert 0 == m.sensor_list # must not been set by an inverter data ind
|
assert 0 == m.sensor_list # must not been set by an inverter data ind
|
||||||
|
|
||||||
m.ifc.write.clear() # clear send buffer for next test
|
m.ifc.tx_clear() # clear send buffer for next test
|
||||||
m._init_new_client_conn()
|
m._init_new_client_conn()
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_build_modell_1600(config_tsun_allow_all, inverter_ind_msg1600):
|
def test_build_modell_1600(config_tsun_allow_all, inverter_ind_msg1600):
|
||||||
@@ -1235,9 +1236,9 @@ def test_build_logger_modell(config_tsun_allow_all, device_ind_msg):
|
|||||||
|
|
||||||
def test_msg_iterator():
|
def test_msg_iterator():
|
||||||
Message._registry.clear()
|
Message._registry.clear()
|
||||||
m1 = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfc())
|
m1 = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfcImpl())
|
||||||
m2 = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfc())
|
m2 = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfcImpl())
|
||||||
m3 = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfc())
|
m3 = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfcImpl())
|
||||||
m3.close()
|
m3.close()
|
||||||
del m3
|
del m3
|
||||||
test1 = 0
|
test1 = 0
|
||||||
@@ -1255,7 +1256,7 @@ def test_msg_iterator():
|
|||||||
assert test2 == 1
|
assert test2 == 1
|
||||||
|
|
||||||
def test_proxy_counter():
|
def test_proxy_counter():
|
||||||
m = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfc())
|
m = SolarmanV5(server_side=True, client_mode=False, ifc=AsyncIfcImpl())
|
||||||
assert m.new_data == {}
|
assert m.new_data == {}
|
||||||
m.db.stat['proxy']['Unknown_Msg'] = 0
|
m.db.stat['proxy']['Unknown_Msg'] = 0
|
||||||
Infos.new_stat_data['proxy'] = False
|
Infos.new_stat_data['proxy'] = False
|
||||||
@@ -1279,14 +1280,14 @@ async def test_msg_build_modbus_req(config_tsun_inv1, device_ind_msg, device_rsp
|
|||||||
m.read()
|
m.read()
|
||||||
assert m.control == 0x4110
|
assert m.control == 0x4110
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert m.ifc.write.get()==device_rsp_msg
|
assert m.ifc.tx_fifo.get()==device_rsp_msg
|
||||||
assert m.ifc.forward.get()==device_ind_msg
|
assert m.ifc.fwd_fifo.get()==device_ind_msg
|
||||||
|
|
||||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||||
assert 0 == m.send_msg_ofs
|
assert 0 == m.send_msg_ofs
|
||||||
assert m.ifc.forward.get() == b''
|
assert m.ifc.fwd_fifo.get() == b''
|
||||||
assert m.sent_pdu == b'' # modbus command must be ignore, cause connection is still not up
|
assert m.sent_pdu == b'' # modbus command must be ignore, cause connection is still not up
|
||||||
assert m.ifc.write.get() == b'' # modbus command must be ignore, cause connection is still not up
|
assert m.ifc.tx_fifo.get() == b'' # modbus command must be ignore, cause connection is still not up
|
||||||
|
|
||||||
m.append_msg(inverter_ind_msg)
|
m.append_msg(inverter_ind_msg)
|
||||||
m.read()
|
m.read()
|
||||||
@@ -1296,15 +1297,15 @@ async def test_msg_build_modbus_req(config_tsun_inv1, device_ind_msg, device_rsp
|
|||||||
assert m.msg_recvd[0]['seq']=='01:01'
|
assert m.msg_recvd[0]['seq']=='01:01'
|
||||||
assert m.msg_recvd[1]['control']==0x4210
|
assert m.msg_recvd[1]['control']==0x4210
|
||||||
assert m.msg_recvd[1]['seq']=='02:02'
|
assert m.msg_recvd[1]['seq']=='02:02'
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==inverter_rsp_msg
|
assert m.ifc.tx_fifo.get()==inverter_rsp_msg
|
||||||
assert m.ifc.forward.get()==inverter_ind_msg
|
assert m.ifc.fwd_fifo.get()==inverter_ind_msg
|
||||||
|
|
||||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||||
assert 0 == m.send_msg_ofs
|
assert 0 == m.send_msg_ofs
|
||||||
assert m.ifc.forward.get() == b''
|
assert m.ifc.fwd_fifo.get() == b''
|
||||||
assert m.sent_pdu == msg_modbus_cmd
|
assert m.sent_pdu == msg_modbus_cmd
|
||||||
assert m.ifc.write.get()== b''
|
assert m.ifc.tx_fifo.get()== b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@@ -1314,12 +1315,12 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
m.read() # read device ind
|
m.read() # read device ind
|
||||||
assert m.control == 0x4110
|
assert m.control == 0x4110
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert m.ifc.write.get()==device_rsp_msg
|
assert m.ifc.tx_fifo.get()==device_rsp_msg
|
||||||
assert m.ifc.forward.get()==device_ind_msg
|
assert m.ifc.fwd_fifo.get()==device_ind_msg
|
||||||
|
|
||||||
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.sent_pdu == b''
|
assert m.sent_pdu == b''
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert m.mqtt.key == ''
|
assert m.mqtt.key == ''
|
||||||
@@ -1329,12 +1330,12 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
m.read() # read inverter ind
|
m.read() # read inverter ind
|
||||||
assert m.control == 0x4210
|
assert m.control == 0x4210
|
||||||
assert str(m.seq) == '02:02'
|
assert str(m.seq) == '02:02'
|
||||||
assert m.ifc.write.get()==inverter_rsp_msg
|
assert m.ifc.tx_fifo.get()==inverter_rsp_msg
|
||||||
assert m.ifc.forward.get()==inverter_ind_msg
|
assert m.ifc.fwd_fifo.get()==inverter_ind_msg
|
||||||
|
|
||||||
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
||||||
assert m.ifc.forward.get() == b''
|
assert m.ifc.fwd_fifo.get() == b''
|
||||||
assert m.ifc.write.get()== b''
|
assert m.ifc.tx_fifo.get()== b''
|
||||||
assert m.sent_pdu == at_command_ind_msg
|
assert m.sent_pdu == at_command_ind_msg
|
||||||
m.sent_pdu = bytearray()
|
m.sent_pdu = bytearray()
|
||||||
|
|
||||||
@@ -1346,9 +1347,9 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
m.read() # read at resp
|
m.read() # read at resp
|
||||||
assert m.control == 0x1510
|
assert m.control == 0x1510
|
||||||
assert str(m.seq) == '03:03'
|
assert str(m.seq) == '03:03'
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.key == 'at_resp'
|
assert m.key == 'at_resp'
|
||||||
assert m.data == "+ok"
|
assert m.data == "+ok"
|
||||||
|
|
||||||
@@ -1356,9 +1357,9 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
m.test_exception_async_write = True
|
m.test_exception_async_write = True
|
||||||
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
await m.send_at_cmd('AT+TIME=214028,1,60,120')
|
||||||
assert m.sent_pdu == b''
|
assert m.sent_pdu == b''
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.sent_pdu == b''
|
assert m.sent_pdu == b''
|
||||||
assert str(m.seq) == '03:04'
|
assert str(m.seq) == '03:04'
|
||||||
assert m.forward_at_cmd_resp == False
|
assert m.forward_at_cmd_resp == False
|
||||||
@@ -1373,12 +1374,12 @@ async def test_at_cmd_blocked(config_tsun_allow_all, device_ind_msg, device_rsp_
|
|||||||
m.read()
|
m.read()
|
||||||
assert m.control == 0x4110
|
assert m.control == 0x4110
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert m.ifc.write.get()==device_rsp_msg
|
assert m.ifc.tx_fifo.get()==device_rsp_msg
|
||||||
assert m.ifc.forward.get()==device_ind_msg
|
assert m.ifc.fwd_fifo.get()==device_ind_msg
|
||||||
|
|
||||||
await m.send_at_cmd('AT+WEBU')
|
await m.send_at_cmd('AT+WEBU')
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert m.mqtt.key == ''
|
assert m.mqtt.key == ''
|
||||||
assert m.mqtt.data == ""
|
assert m.mqtt.data == ""
|
||||||
@@ -1387,14 +1388,14 @@ async def test_at_cmd_blocked(config_tsun_allow_all, device_ind_msg, device_rsp_
|
|||||||
m.read()
|
m.read()
|
||||||
assert m.control == 0x4210
|
assert m.control == 0x4210
|
||||||
assert str(m.seq) == '02:02'
|
assert str(m.seq) == '02:02'
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==inverter_rsp_msg
|
assert m.ifc.tx_fifo.get()==inverter_rsp_msg
|
||||||
assert m.ifc.forward.get()==inverter_ind_msg
|
assert m.ifc.fwd_fifo.get()==inverter_ind_msg
|
||||||
|
|
||||||
await m.send_at_cmd('AT+WEBU')
|
await m.send_at_cmd('AT+WEBU')
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert str(m.seq) == '02:02'
|
assert str(m.seq) == '02:02'
|
||||||
assert m.forward_at_cmd_resp == False
|
assert m.forward_at_cmd_resp == False
|
||||||
assert m.mqtt.key == 'at_resp'
|
assert m.mqtt.key == 'at_resp'
|
||||||
@@ -1416,9 +1417,9 @@ def test_at_cmd_ind(config_tsun_inv1, at_command_ind_msg):
|
|||||||
assert m.control == 0x4510
|
assert m.control == 0x4510
|
||||||
assert str(m.seq) == '03:02'
|
assert str(m.seq) == '03:02'
|
||||||
assert m.data_len == 39
|
assert m.data_len == 39
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==at_command_ind_msg
|
assert m.ifc.fwd_fifo.get()==at_command_ind_msg
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
assert m.db.stat['proxy']['AT_Command'] == 1
|
assert m.db.stat['proxy']['AT_Command'] == 1
|
||||||
assert m.db.stat['proxy']['AT_Command_Blocked'] == 0
|
assert m.db.stat['proxy']['AT_Command_Blocked'] == 0
|
||||||
@@ -1440,9 +1441,9 @@ def test_at_cmd_ind_block(config_tsun_inv1, at_command_ind_msg_block):
|
|||||||
assert m.control == 0x4510
|
assert m.control == 0x4510
|
||||||
assert str(m.seq) == '03:02'
|
assert str(m.seq) == '03:02'
|
||||||
assert m.data_len == 23
|
assert m.data_len == 23
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||||
assert m.db.stat['proxy']['AT_Command_Blocked'] == 1
|
assert m.db.stat['proxy']['AT_Command_Blocked'] == 1
|
||||||
@@ -1462,8 +1463,8 @@ def test_msg_at_command_rsp1(config_tsun_inv1, at_command_rsp_msg):
|
|||||||
assert str(m.seq) == '03:03'
|
assert str(m.seq) == '03:03'
|
||||||
assert m.header_len==11
|
assert m.header_len==11
|
||||||
assert m.data_len==17
|
assert m.data_len==17
|
||||||
assert m.ifc.forward.get()==at_command_rsp_msg
|
assert m.ifc.fwd_fifo.get()==at_command_rsp_msg
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1481,8 +1482,8 @@ def test_msg_at_command_rsp2(config_tsun_inv1, at_command_rsp_msg):
|
|||||||
assert str(m.seq) == '03:03'
|
assert str(m.seq) == '03:03'
|
||||||
assert m.header_len==11
|
assert m.header_len==11
|
||||||
assert m.data_len==17
|
assert m.data_len==17
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1506,8 +1507,8 @@ def test_msg_modbus_req(config_tsun_inv1, msg_modbus_cmd, msg_modbus_cmd_fwd):
|
|||||||
assert str(c.seq) == '03:02'
|
assert str(c.seq) == '03:02'
|
||||||
assert c.header_len==11
|
assert c.header_len==11
|
||||||
assert c.data_len==23
|
assert c.data_len==23
|
||||||
assert c.ifc.forward.get()==b''
|
assert c.ifc.fwd_fifo.get()==b''
|
||||||
assert c.ifc.write.get()==b''
|
assert c.ifc.tx_fifo.get()==b''
|
||||||
assert m.sent_pdu == msg_modbus_cmd_fwd
|
assert m.sent_pdu == msg_modbus_cmd_fwd
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||||
@@ -1533,8 +1534,8 @@ def test_msg_modbus_req2(config_tsun_inv1, msg_modbus_cmd_crc_err):
|
|||||||
assert str(c.seq) == '03:02'
|
assert str(c.seq) == '03:02'
|
||||||
assert c.header_len==11
|
assert c.header_len==11
|
||||||
assert c.data_len==23
|
assert c.data_len==23
|
||||||
assert c.ifc.forward.get()==b''
|
assert c.ifc.fwd_fifo.get()==b''
|
||||||
assert c.ifc.write.get()==b''
|
assert c.ifc.tx_fifo.get()==b''
|
||||||
assert m.sent_pdu==b''
|
assert m.sent_pdu==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||||
@@ -1556,8 +1557,8 @@ def test_msg_unknown_cmd_req(config_tsun_inv1, msg_unknown_cmd):
|
|||||||
assert str(m.seq) == '03:02'
|
assert str(m.seq) == '03:02'
|
||||||
assert m.header_len==11
|
assert m.header_len==11
|
||||||
assert m.data_len==23
|
assert m.data_len==23
|
||||||
assert m.ifc.forward.get()==msg_unknown_cmd
|
assert m.ifc.fwd_fifo.get()==msg_unknown_cmd
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
assert m.db.stat['proxy']['AT_Command'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
@@ -1577,8 +1578,8 @@ def test_msg_modbus_rsp1(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
assert str(m.seq) == '03:03'
|
assert str(m.seq) == '03:03'
|
||||||
assert m.header_len==11
|
assert m.header_len==11
|
||||||
assert m.data_len==59
|
assert m.data_len==59
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1601,8 +1602,8 @@ def test_msg_modbus_rsp2(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.mb.err == 0
|
assert m.mb.err == 0
|
||||||
assert m.msg_count == 1
|
assert m.msg_count == 1
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||||
assert m.new_data['inverter'] == True
|
assert m.new_data['inverter'] == True
|
||||||
m.new_data['inverter'] = False
|
m.new_data['inverter'] = False
|
||||||
@@ -1613,8 +1614,8 @@ def test_msg_modbus_rsp2(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.mb.err == 0
|
assert m.mb.err == 0
|
||||||
assert m.msg_count == 2
|
assert m.msg_count == 2
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||||
assert m.new_data['inverter'] == False
|
assert m.new_data['inverter'] == False
|
||||||
|
|
||||||
@@ -1638,8 +1639,8 @@ def test_msg_modbus_rsp3(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.mb.err == 0
|
assert m.mb.err == 0
|
||||||
assert m.msg_count == 1
|
assert m.msg_count == 1
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||||
assert m.new_data['inverter'] == True
|
assert m.new_data['inverter'] == True
|
||||||
m.new_data['inverter'] = False
|
m.new_data['inverter'] = False
|
||||||
@@ -1649,8 +1650,8 @@ def test_msg_modbus_rsp3(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.mb.err == 5
|
assert m.mb.err == 5
|
||||||
assert m.msg_count == 2
|
assert m.msg_count == 2
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
assert m.db.get_db_value(Register.VERSION) == 'V4.0.10'
|
||||||
assert m.new_data['inverter'] == False
|
assert m.new_data['inverter'] == False
|
||||||
|
|
||||||
@@ -1668,8 +1669,8 @@ def test_msg_unknown_rsp(config_tsun_inv1, msg_unknown_cmd_rsp):
|
|||||||
assert str(m.seq) == '03:03'
|
assert str(m.seq) == '03:03'
|
||||||
assert m.header_len==11
|
assert m.header_len==11
|
||||||
assert m.data_len==59
|
assert m.data_len==59
|
||||||
assert m.ifc.forward.get()==msg_unknown_cmd_rsp
|
assert m.ifc.fwd_fifo.get()==msg_unknown_cmd_rsp
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1682,8 +1683,8 @@ def test_msg_modbus_invalid(config_tsun_inv1, msg_modbus_invalid):
|
|||||||
m.read() # read complete msg, and dispatch msg
|
m.read() # read complete msg, and dispatch msg
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.msg_count == 1
|
assert m.msg_count == 1
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1705,8 +1706,8 @@ def test_msg_modbus_fragment(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
m.read() # read complete msg, and dispatch msg
|
m.read() # read complete msg, and dispatch msg
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.msg_count == 1
|
assert m.msg_count == 1
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp
|
||||||
assert m.ifc.write.get()== b''
|
assert m.ifc.tx_fifo.get()== b''
|
||||||
assert m.mb.err == 0
|
assert m.mb.err == 0
|
||||||
assert m.modbus_elms == 20-1 # register 0x300d is unknown, so one value can't be mapped
|
assert m.modbus_elms == 20-1 # register 0x300d is unknown, so one value can't be mapped
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
@@ -1729,9 +1730,9 @@ async def test_modbus_polling(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp
|
|||||||
assert m.control == 0x4710
|
assert m.control == 0x4710
|
||||||
assert str(m.seq) == '84:11' # value after sending response
|
assert str(m.seq) == '84:11' # value after sending response
|
||||||
assert m.data_len == 0x01
|
assert m.data_len == 0x01
|
||||||
assert m.ifc.read.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.write.get()==heartbeat_rsp_msg
|
assert m.ifc.tx_fifo.get()==heartbeat_rsp_msg
|
||||||
assert m.ifc.forward.get()==heartbeat_ind_msg
|
assert m.ifc.fwd_fifo.get()==heartbeat_ind_msg
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
|
|
||||||
assert m.state == State.up
|
assert m.state == State.up
|
||||||
@@ -1740,16 +1741,16 @@ async def test_modbus_polling(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp
|
|||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x12\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x86\x15')
|
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x12\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x86\x15')
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x13\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x87\x15')
|
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x13\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x30\x00\x000J\xde\x87\x15')
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
m.state = State.closed
|
m.state = State.closed
|
||||||
m.sent_pdu = bytearray()
|
m.sent_pdu = bytearray()
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==bytearray(b'')
|
assert m.sent_pdu==bytearray(b'')
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert next(m.mb_timer.exp_count) == 4
|
assert next(m.mb_timer.exp_count) == 4
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1771,16 +1772,29 @@ async def test_start_client_mode(config_tsun_inv1, str_test_ip):
|
|||||||
assert m.state == State.up
|
assert m.state == State.up
|
||||||
assert m.no_forwarding == True
|
assert m.no_forwarding == True
|
||||||
|
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert isclose(m.mb_timeout, 0.5)
|
assert isclose(m.mb_timeout, 0.5)
|
||||||
assert next(m.mb_timer.exp_count) == 0
|
assert next(m.mb_timer.exp_count) == 0
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x02\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf2\x15')
|
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x02\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf2\x15')
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x03\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf3\x15')
|
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x03\x00!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x030\x00\x000J\xde\xf3\x15')
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert next(m.mb_timer.exp_count) == 3
|
assert next(m.mb_timer.exp_count) == 3
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
|
def test_timeout(config_tsun_inv1):
|
||||||
|
_ = config_tsun_inv1
|
||||||
|
m = MemoryStream(b'')
|
||||||
|
assert m.state == State.init
|
||||||
|
assert SolarmanV5.MAX_START_TIME == m._timeout()
|
||||||
|
m.state = State.up
|
||||||
|
m.modbus_polling = True
|
||||||
|
assert SolarmanV5.MAX_INV_IDLE_TIME == m._timeout()
|
||||||
|
m.modbus_polling = False
|
||||||
|
assert SolarmanV5.MAX_DEF_IDLE_TIME == m._timeout()
|
||||||
|
m.state = State.closed
|
||||||
|
m.close()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# test_with_pytest.py
|
# test_with_pytest.py
|
||||||
import pytest, logging, asyncio
|
import pytest, logging, asyncio
|
||||||
from math import isclose
|
from math import isclose
|
||||||
from app.src.async_ifc import AsyncIfc
|
from app.src.async_stream import AsyncIfcImpl, StreamPtr
|
||||||
from app.src.gen3.talent import Talent, Control
|
from app.src.gen3.talent import Talent, Control
|
||||||
from app.src.config import Config
|
from app.src.config import Config
|
||||||
from app.src.infos import Infos, Register
|
from app.src.infos import Infos, Register
|
||||||
@@ -19,13 +19,15 @@ tracer = logging.getLogger('tracer')
|
|||||||
|
|
||||||
class MemoryStream(Talent):
|
class MemoryStream(Talent):
|
||||||
def __init__(self, msg, chunks = (0,), server_side: bool = True):
|
def __init__(self, msg, chunks = (0,), server_side: bool = True):
|
||||||
super().__init__(server_side, AsyncIfc())
|
self.ifc = AsyncIfcImpl()
|
||||||
|
super().__init__(server_side, self.ifc)
|
||||||
if server_side:
|
if server_side:
|
||||||
self.mb.timeout = 0.4 # overwrite for faster testing
|
self.mb.timeout = 0.4 # overwrite for faster testing
|
||||||
|
self.remote = StreamPtr(None)
|
||||||
self.mb_first_timeout = 0.5
|
self.mb_first_timeout = 0.5
|
||||||
self.mb_timeout = 0.5
|
self.mb_timeout = 0.5
|
||||||
self.sent_pdu = b''
|
self.sent_pdu = b''
|
||||||
self.ifc.write.reg_trigger(self.write_cb)
|
self.ifc.tx_fifo.reg_trigger(self.write_cb)
|
||||||
self.__msg = msg
|
self.__msg = msg
|
||||||
self.__msg_len = len(msg)
|
self.__msg_len = len(msg)
|
||||||
self.__chunks = chunks
|
self.__chunks = chunks
|
||||||
@@ -35,10 +37,10 @@ class MemoryStream(Talent):
|
|||||||
self.addr = 'Test: SrvSide'
|
self.addr = 'Test: SrvSide'
|
||||||
self.send_msg_ofs = 0
|
self.send_msg_ofs = 0
|
||||||
self.msg_recvd = []
|
self.msg_recvd = []
|
||||||
self.remote_stream = None
|
self.remote.stream = None
|
||||||
|
|
||||||
def write_cb(self):
|
def write_cb(self):
|
||||||
self.sent_pdu = self.ifc.write.get()
|
self.sent_pdu = self.ifc.tx_fifo.get()
|
||||||
|
|
||||||
|
|
||||||
def append_msg(self, msg):
|
def append_msg(self, msg):
|
||||||
@@ -52,11 +54,11 @@ class MemoryStream(Talent):
|
|||||||
chunk_len = self.__chunks[self.__chunk_idx]
|
chunk_len = self.__chunks[self.__chunk_idx]
|
||||||
self.__chunk_idx += 1
|
self.__chunk_idx += 1
|
||||||
if chunk_len!=0:
|
if chunk_len!=0:
|
||||||
self.ifc.read += self.__msg[self.__offs:chunk_len]
|
self.ifc.rx_fifo += self.__msg[self.__offs:chunk_len]
|
||||||
copied_bytes = chunk_len - self.__offs
|
copied_bytes = chunk_len - self.__offs
|
||||||
self.__offs = chunk_len
|
self.__offs = chunk_len
|
||||||
else:
|
else:
|
||||||
self.ifc.read += self.__msg[self.__offs:]
|
self.ifc.rx_fifo += self.__msg[self.__offs:]
|
||||||
copied_bytes = self.__msg_len - self.__offs
|
copied_bytes = self.__msg_len - self.__offs
|
||||||
self.__offs = self.__msg_len
|
self.__offs = self.__msg_len
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -71,8 +73,8 @@ class MemoryStream(Talent):
|
|||||||
|
|
||||||
def createClientStream(self, msg, chunks = (0,)):
|
def createClientStream(self, msg, chunks = (0,)):
|
||||||
c = MemoryStream(msg, chunks, False)
|
c = MemoryStream(msg, chunks, False)
|
||||||
self.remote_stream = c
|
self.remote.stream = c
|
||||||
c. remote_stream = self
|
c. remote.stream = self
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def _Talent__flush_recv_msg(self) -> None:
|
def _Talent__flush_recv_msg(self) -> None:
|
||||||
@@ -741,7 +743,9 @@ def test_read_message(msg_contact_info):
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==25
|
assert m.data_len==25
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_read_message_twice(config_no_tsun_inv1, msg_inverter_ind):
|
def test_read_message_twice(config_no_tsun_inv1, msg_inverter_ind):
|
||||||
@@ -761,7 +765,7 @@ def test_read_message_twice(config_no_tsun_inv1, msg_inverter_ind):
|
|||||||
assert m.msg_recvd[1]['data_len']==120
|
assert m.msg_recvd[1]['data_len']==120
|
||||||
assert m.id_str == b"R170000000000001"
|
assert m.id_str == b"R170000000000001"
|
||||||
assert m.unique_id == 'R170000000000001'
|
assert m.unique_id == 'R170000000000001'
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_read_message_long_id(msg_contact_info_long_id):
|
def test_read_message_long_id(msg_contact_info_long_id):
|
||||||
@@ -846,15 +850,15 @@ def test_read_two_messages(config_tsun_allow_all, msg2_contact_info,msg_contact_
|
|||||||
assert m.msg_recvd[1]['msg_id']==0
|
assert m.msg_recvd[1]['msg_id']==0
|
||||||
assert m.msg_recvd[1]['header_len']==23
|
assert m.msg_recvd[1]['header_len']==23
|
||||||
assert m.msg_recvd[1]['data_len']==25
|
assert m.msg_recvd[1]['data_len']==25
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==msg_contact_rsp + msg_contact_rsp2
|
assert m.ifc.tx_fifo.get()==msg_contact_rsp + msg_contact_rsp2
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
|
|
||||||
m.ifc.write.clear() # clear send buffer for next test
|
m.ifc.tx_clear() # clear send buffer for next test
|
||||||
m.contact_name = b'solarhub'
|
m.contact_name = b'solarhub'
|
||||||
m.contact_mail = b'solarhub@123456'
|
m.contact_mail = b'solarhub@123456'
|
||||||
m._init_new_client_conn()
|
m._init_new_client_conn()
|
||||||
assert m.ifc.write.get()==b'\x00\x00\x00,\x10R170000000000002\x91\x00\x08solarhub\x0fsolarhub@123456'
|
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00,\x10R170000000000002\x91\x00\x08solarhub\x0fsolarhub@123456'
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
||||||
@@ -871,8 +875,8 @@ def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==25
|
assert m.data_len==25
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==msg_contact_rsp
|
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_contact_rsp):
|
def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_contact_rsp):
|
||||||
@@ -889,8 +893,8 @@ def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==23
|
assert m.data_len==23
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==msg_contact_rsp
|
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
||||||
@@ -907,8 +911,8 @@ def test_conttact_req(config_tsun_allow_all, msg_contact_info, msg_contact_rsp):
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==25
|
assert m.data_len==25
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==msg_contact_rsp
|
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_contact_rsp):
|
def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_contact_rsp):
|
||||||
@@ -925,8 +929,8 @@ def test_contact_broken_req(config_tsun_allow_all, msg_contact_info_broken, msg_
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==23
|
assert m.data_len==23
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==msg_contact_rsp
|
assert m.ifc.tx_fifo.get()==msg_contact_rsp
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_msg_contact_resp(config_tsun_inv1, msg_contact_rsp):
|
def test_msg_contact_resp(config_tsun_inv1, msg_contact_rsp):
|
||||||
@@ -944,8 +948,8 @@ def test_msg_contact_resp(config_tsun_inv1, msg_contact_rsp):
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -964,8 +968,8 @@ def test_msg_contact_resp_2(config_tsun_inv1, msg_contact_rsp):
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==msg_contact_rsp
|
assert m.ifc.fwd_fifo.get()==msg_contact_rsp
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -984,8 +988,8 @@ def test_msg_contact_resp_3(config_tsun_inv1, msg_contact_rsp):
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==msg_contact_rsp
|
assert m.ifc.fwd_fifo.get()==msg_contact_rsp
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1002,8 +1006,8 @@ def test_msg_contact_invalid(config_tsun_inv1, msg_contact_invalid):
|
|||||||
assert m.msg_id==0
|
assert m.msg_id==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==msg_contact_invalid
|
assert m.ifc.fwd_fifo.get()==msg_contact_invalid
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1023,8 +1027,8 @@ def test_msg_get_time(config_tsun_inv1, msg_get_time):
|
|||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.data_len==0
|
assert m.data_len==0
|
||||||
assert m.state==State.pend
|
assert m.state==State.pend
|
||||||
assert m.ifc.forward.get()==msg_get_time
|
assert m.ifc.fwd_fifo.get()==msg_get_time
|
||||||
assert m.ifc.write.get()==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1044,8 +1048,8 @@ def test_msg_get_time_autark(config_no_tsun_inv1, msg_get_time):
|
|||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.data_len==0
|
assert m.data_len==0
|
||||||
assert m.state==State.received
|
assert m.state==State.received
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==bytearray(b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00')
|
assert m.ifc.tx_fifo.get()==bytearray(b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00')
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1055,7 +1059,7 @@ def test_msg_time_resp(config_tsun_inv1, msg_time_rsp):
|
|||||||
m = MemoryStream(msg_time_rsp, (0,), False)
|
m = MemoryStream(msg_time_rsp, (0,), False)
|
||||||
s = MemoryStream(b'', (0,), True)
|
s = MemoryStream(b'', (0,), True)
|
||||||
assert s.ts_offset==0
|
assert s.ts_offset==0
|
||||||
m.remote_stream = s
|
m.remote.stream = s
|
||||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
||||||
m.read() # read complete msg, and dispatch msg
|
m.read() # read complete msg, and dispatch msg
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
@@ -1068,10 +1072,10 @@ def test_msg_time_resp(config_tsun_inv1, msg_time_rsp):
|
|||||||
assert m.ts_offset==3600000
|
assert m.ts_offset==3600000
|
||||||
assert s.ts_offset==3600000
|
assert s.ts_offset==3600000
|
||||||
assert m.data_len==8
|
assert m.data_len==8
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.remote_stream = None
|
m.remote.stream = None
|
||||||
s.close()
|
s.close()
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1089,8 +1093,8 @@ def test_msg_time_resp_autark(config_no_tsun_inv1, msg_time_rsp):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.ts_offset==3600000
|
assert m.ts_offset==3600000
|
||||||
assert m.data_len==8
|
assert m.data_len==8
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1108,8 +1112,8 @@ def test_msg_time_inv_resp(config_tsun_inv1, msg_time_rsp_inv):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.data_len==4
|
assert m.data_len==4
|
||||||
assert m.ifc.forward.get()==msg_time_rsp_inv
|
assert m.ifc.fwd_fifo.get()==msg_time_rsp_inv
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1127,8 +1131,8 @@ def test_msg_time_invalid(config_tsun_inv1, msg_time_invalid):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.data_len==0
|
assert m.data_len==0
|
||||||
assert m.ifc.forward.get()==msg_time_invalid
|
assert m.ifc.fwd_fifo.get()==msg_time_invalid
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1146,8 +1150,8 @@ def test_msg_time_invalid_autark(config_no_tsun_inv1, msg_time_invalid):
|
|||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==0
|
assert m.data_len==0
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1170,8 +1174,8 @@ def test_msg_act_time(config_no_modbus_poll, msg_act_time, msg_act_time_ack):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==9
|
assert m.data_len==9
|
||||||
assert m.state == State.up
|
assert m.state == State.up
|
||||||
assert m.ifc.forward.get()==msg_act_time
|
assert m.ifc.fwd_fifo.get()==msg_act_time
|
||||||
assert m.ifc.write.get()==msg_act_time_ack
|
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert 125 == m.db.get_db_value(Register.POLLING_INTERVAL, 0)
|
assert 125 == m.db.get_db_value(Register.POLLING_INTERVAL, 0)
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1194,8 +1198,8 @@ def test_msg_act_time2(config_tsun_inv1, msg_act_time, msg_act_time_ack):
|
|||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==9
|
assert m.data_len==9
|
||||||
assert m.ifc.forward.get()==msg_act_time
|
assert m.ifc.fwd_fifo.get()==msg_act_time
|
||||||
assert m.ifc.write.get()==msg_act_time_ack
|
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert 123 == m.db.get_db_value(Register.POLLING_INTERVAL, 0)
|
assert 123 == m.db.get_db_value(Register.POLLING_INTERVAL, 0)
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1215,8 +1219,8 @@ def test_msg_act_time_ofs(config_tsun_inv1, msg_act_time, msg_act_time_ofs, msg_
|
|||||||
assert m.ts_offset==3600
|
assert m.ts_offset==3600
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==9
|
assert m.data_len==9
|
||||||
assert m.ifc.forward.get()==msg_act_time_ofs
|
assert m.ifc.fwd_fifo.get()==msg_act_time_ofs
|
||||||
assert m.ifc.write.get()==msg_act_time_ack
|
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1235,8 +1239,8 @@ def test_msg_act_time_ofs2(config_tsun_inv1, msg_act_time, msg_act_time_ofs, msg
|
|||||||
assert m.ts_offset==-3600
|
assert m.ts_offset==-3600
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==9
|
assert m.data_len==9
|
||||||
assert m.ifc.forward.get()==msg_act_time
|
assert m.ifc.fwd_fifo.get()==msg_act_time
|
||||||
assert m.ifc.write.get()==msg_act_time_ack
|
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1255,8 +1259,8 @@ def test_msg_act_time_autark(config_no_tsun_inv1, msg_act_time, msg_act_time_ack
|
|||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==9
|
assert m.data_len==9
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==msg_act_time_ack
|
assert m.ifc.tx_fifo.get()==msg_act_time_ack
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1273,8 +1277,8 @@ def test_msg_act_time_ack(config_tsun_inv1, msg_act_time_ack):
|
|||||||
assert m.msg_id==153
|
assert m.msg_id==153
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1291,8 +1295,8 @@ def test_msg_act_time_cmd(config_tsun_inv1, msg_act_time_cmd):
|
|||||||
assert m.msg_id==153
|
assert m.msg_id==153
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==msg_act_time_cmd
|
assert m.ifc.fwd_fifo.get()==msg_act_time_cmd
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1309,8 +1313,8 @@ def test_msg_act_time_inv(config_tsun_inv1, msg_act_time_inv):
|
|||||||
assert m.msg_id==153
|
assert m.msg_id==153
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==8
|
assert m.data_len==8
|
||||||
assert m.ifc.forward.get()==msg_act_time_inv
|
assert m.ifc.fwd_fifo.get()==msg_act_time_inv
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1328,12 +1332,12 @@ def test_msg_cntrl_ind(config_tsun_inv1, msg_controller_ind, msg_controller_ind_
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==284
|
assert m.data_len==284
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.peek()==msg_controller_ind
|
assert m.ifc.fwd_fifo.peek()==msg_controller_ind
|
||||||
m.ts_offset = -4096
|
m.ts_offset = -4096
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_controller_ind_ts_offs
|
assert m.ifc.fwd_fifo.get()==msg_controller_ind_ts_offs
|
||||||
assert m.ifc.write.get()==msg_controller_ack
|
assert m.ifc.tx_fifo.get()==msg_controller_ack
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1350,8 +1354,8 @@ def test_msg_cntrl_ack(config_tsun_inv1, msg_controller_ack):
|
|||||||
assert m.msg_id==113
|
assert m.msg_id==113
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1369,12 +1373,12 @@ def test_msg_cntrl_invalid(config_tsun_inv1, msg_controller_invalid):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.peek()==msg_controller_invalid
|
assert m.ifc.fwd_fifo.peek()==msg_controller_invalid
|
||||||
m.ts_offset = -4096
|
m.ts_offset = -4096
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_controller_invalid
|
assert m.ifc.fwd_fifo.get()==msg_controller_invalid
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1393,12 +1397,12 @@ def test_msg_inv_ind(config_tsun_inv1, msg_inverter_ind, msg_inverter_ind_ts_off
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==120
|
assert m.data_len==120
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.peek()==msg_inverter_ind
|
assert m.ifc.fwd_fifo.peek()==msg_inverter_ind
|
||||||
m.ts_offset = +256
|
m.ts_offset = +256
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_inverter_ind_ts_offs
|
assert m.ifc.fwd_fifo.get()==msg_inverter_ind_ts_offs
|
||||||
assert m.ifc.write.get()==msg_inverter_ack
|
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1420,9 +1424,9 @@ def test_msg_inv_ind1(config_tsun_inv1, msg_inverter_ind2, msg_inverter_ind_ts_o
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1263
|
assert m.data_len==1263
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_inverter_ind2
|
assert m.ifc.fwd_fifo.get()==msg_inverter_ind2
|
||||||
assert m.ifc.write.get()==msg_inverter_ack
|
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||||
assert m.db.get_db_value(Register.TS_GRID) == 1691243349
|
assert m.db.get_db_value(Register.TS_GRID) == 1691243349
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1444,9 +1448,9 @@ def test_msg_inv_ind2(config_tsun_inv1, msg_inverter_ind_new, msg_inverter_ind_t
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1165
|
assert m.data_len==1165
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_inverter_ind_new
|
assert m.ifc.fwd_fifo.get()==msg_inverter_ind_new
|
||||||
assert m.ifc.write.get()==msg_inverter_ack
|
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||||
assert m.db.get_db_value(Register.INVERTER_STATUS) == None
|
assert m.db.get_db_value(Register.INVERTER_STATUS) == None
|
||||||
assert m.db.get_db_value(Register.TS_GRID) == None
|
assert m.db.get_db_value(Register.TS_GRID) == None
|
||||||
m.db.db['grid'] = {'Output_Power': 100}
|
m.db.db['grid'] = {'Output_Power': 100}
|
||||||
@@ -1472,9 +1476,9 @@ def test_msg_inv_ind3(config_tsun_inv1, msg_inverter_ind_0w, msg_inverter_ack):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1263
|
assert m.data_len==1263
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_inverter_ind_0w
|
assert m.ifc.fwd_fifo.get()==msg_inverter_ind_0w
|
||||||
assert m.ifc.write.get()==msg_inverter_ack
|
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
||||||
assert m.db.get_db_value(Register.INVERTER_STATUS) == 1
|
assert m.db.get_db_value(Register.INVERTER_STATUS) == 1
|
||||||
assert isclose(m.db.db['grid']['Output_Power'], 0.5)
|
assert isclose(m.db.db['grid']['Output_Power'], 0.5)
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1496,8 +1500,8 @@ def test_msg_inv_ack(config_tsun_inv1, msg_inverter_ack):
|
|||||||
assert m.msg_id==4
|
assert m.msg_id==4
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1515,12 +1519,12 @@ def test_msg_inv_invalid(config_tsun_inv1, msg_inverter_invalid):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.peek()==msg_inverter_invalid
|
assert m.ifc.fwd_fifo.peek()==msg_inverter_invalid
|
||||||
m.ts_offset = 256
|
m.ts_offset = 256
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_inverter_invalid
|
assert m.ifc.fwd_fifo.get()==msg_inverter_invalid
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1539,12 +1543,12 @@ def test_msg_ota_req(config_tsun_inv1, msg_ota_req):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==259
|
assert m.data_len==259
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.peek()==msg_ota_req
|
assert m.ifc.fwd_fifo.peek()==msg_ota_req
|
||||||
m.ts_offset = 4096
|
m.ts_offset = 4096
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_ota_req
|
assert m.ifc.fwd_fifo.get()==msg_ota_req
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['OTA_Start_Msg'] == 1
|
assert m.db.stat['proxy']['OTA_Start_Msg'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1566,12 +1570,12 @@ def test_msg_ota_ack(config_tsun_inv1, msg_ota_ack):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.peek()==msg_ota_ack
|
assert m.ifc.fwd_fifo.peek()==msg_ota_ack
|
||||||
m.ts_offset = 256
|
m.ts_offset = 256
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.get()==msg_ota_ack
|
assert m.ifc.fwd_fifo.get()==msg_ota_ack
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['OTA_Start_Msg'] == 0
|
assert m.db.stat['proxy']['OTA_Start_Msg'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1591,12 +1595,12 @@ def test_msg_ota_invalid(config_tsun_inv1, msg_ota_invalid):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==1
|
assert m.data_len==1
|
||||||
m.ts_offset = 0
|
m.ts_offset = 0
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.forward.peek()==msg_ota_invalid
|
assert m.ifc.fwd_fifo.peek()==msg_ota_invalid
|
||||||
m.ts_offset = 4096
|
m.ts_offset = 4096
|
||||||
assert m.ifc.forward.get()==msg_ota_invalid
|
assert m.ifc.fwd_fifo.get()==msg_ota_invalid
|
||||||
m._update_header(m.ifc.forward.peek())
|
m._update_header(m.ifc.fwd_fifo.peek())
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
assert m.db.stat['proxy']['OTA_Start_Msg'] == 0
|
assert m.db.stat['proxy']['OTA_Start_Msg'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1614,8 +1618,8 @@ def test_msg_unknown(config_tsun_inv1, msg_unknown):
|
|||||||
assert m.msg_id==23
|
assert m.msg_id==23
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==4
|
assert m.data_len==4
|
||||||
assert m.ifc.forward.get()==msg_unknown
|
assert m.ifc.fwd_fifo.get()==msg_unknown
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert 1 == m.db.stat['proxy']['Unknown_Msg']
|
assert 1 == m.db.stat['proxy']['Unknown_Msg']
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -1635,9 +1639,9 @@ def test_ctrl_byte():
|
|||||||
|
|
||||||
|
|
||||||
def test_msg_iterator():
|
def test_msg_iterator():
|
||||||
m1 = Talent(server_side=True, ifc=AsyncIfc())
|
m1 = Talent(server_side=True, ifc=AsyncIfcImpl())
|
||||||
m2 = Talent(server_side=True, ifc=AsyncIfc())
|
m2 = Talent(server_side=True, ifc=AsyncIfcImpl())
|
||||||
m3 = Talent(server_side=True, ifc=AsyncIfc())
|
m3 = Talent(server_side=True, ifc=AsyncIfcImpl())
|
||||||
m3.close()
|
m3.close()
|
||||||
del m3
|
del m3
|
||||||
test1 = 0
|
test1 = 0
|
||||||
@@ -1739,11 +1743,11 @@ def test_msg_modbus_req(config_tsun_inv1, msg_modbus_cmd):
|
|||||||
assert c.msg_id==119
|
assert c.msg_id==119
|
||||||
assert c.header_len==23
|
assert c.header_len==23
|
||||||
assert c.data_len==13
|
assert c.data_len==13
|
||||||
assert c.ifc.forward.get()==b''
|
assert c.ifc.fwd_fifo.get()==b''
|
||||||
assert c.ifc.write.get()==b''
|
assert c.ifc.tx_fifo.get()==b''
|
||||||
assert m.id_str == b"R170000000000001"
|
assert m.id_str == b"R170000000000001"
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.sent_pdu == msg_modbus_cmd
|
assert m.sent_pdu == msg_modbus_cmd
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 1
|
assert m.db.stat['proxy']['Modbus_Command'] == 1
|
||||||
@@ -1769,11 +1773,11 @@ def test_msg_modbus_req2(config_tsun_inv1, msg_modbus_cmd):
|
|||||||
assert c.msg_id==119
|
assert c.msg_id==119
|
||||||
assert c.header_len==23
|
assert c.header_len==23
|
||||||
assert c.data_len==13
|
assert c.data_len==13
|
||||||
assert c.ifc.forward.get()==b''
|
assert c.ifc.fwd_fifo.get()==b''
|
||||||
assert c.ifc.write.get()==b''
|
assert c.ifc.tx_fifo.get()==b''
|
||||||
assert m.id_str == b"R170000000000001"
|
assert m.id_str == b"R170000000000001"
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.sent_pdu == b''
|
assert m.sent_pdu == b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 1
|
assert m.db.stat['proxy']['Modbus_Command'] == 1
|
||||||
@@ -1798,10 +1802,10 @@ def test_msg_modbus_req3(config_tsun_inv1, msg_modbus_cmd_crc_err):
|
|||||||
assert c.msg_id==119
|
assert c.msg_id==119
|
||||||
assert c.header_len==23
|
assert c.header_len==23
|
||||||
assert c.data_len==13
|
assert c.data_len==13
|
||||||
assert c.ifc.forward.get()==b''
|
assert c.ifc.fwd_fifo.get()==b''
|
||||||
assert c.ifc.write.get()==b''
|
assert c.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.sent_pdu ==b''
|
assert m.sent_pdu ==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
@@ -1823,8 +1827,8 @@ def test_msg_modbus_rsp1(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
assert m.msg_id==119
|
assert m.msg_id==119
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==13
|
assert m.data_len==13
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1845,8 +1849,8 @@ def test_msg_modbus_cloud_rsp(config_tsun_inv1, msg_modbus_rsp):
|
|||||||
assert m.msg_id==119
|
assert m.msg_id==119
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==13
|
assert m.data_len==13
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Msg'] == 1
|
assert m.db.stat['proxy']['Unknown_Msg'] == 1
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
@@ -1873,8 +1877,8 @@ def test_msg_modbus_rsp2(config_tsun_inv1, msg_modbus_rsp20):
|
|||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.mb.err == 5
|
assert m.mb.err == 5
|
||||||
assert m.msg_count == 2
|
assert m.msg_count == 2
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp20
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp20
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.db == {'collector': {'Serial_Number': 'R170000000000001'}, 'inverter': {'Version': 'V5.1.09', 'Rated_Power': 300}, 'grid': {'Timestamp': m._utc(), 'Voltage': 225.9, 'Current': 0.41, 'Frequency': 49.99, 'Output_Power': 94.8}, 'env': {'Inverter_Temp': 22}, 'input': {'Timestamp': m._utc(), 'pv1': {'Voltage': 0.8, 'Current': 0.0, 'Power': 0.0}, 'pv2': {'Voltage': 34.5, 'Current': 2.89, 'Power': 99.8}, 'pv3': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}, 'pv4': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}}}
|
assert m.db.db == {'collector': {'Serial_Number': 'R170000000000001'}, 'inverter': {'Version': 'V5.1.09', 'Rated_Power': 300}, 'grid': {'Timestamp': m._utc(), 'Voltage': 225.9, 'Current': 0.41, 'Frequency': 49.99, 'Output_Power': 94.8}, 'env': {'Inverter_Temp': 22}, 'input': {'Timestamp': m._utc(), 'pv1': {'Voltage': 0.8, 'Current': 0.0, 'Power': 0.0}, 'pv2': {'Voltage': 34.5, 'Current': 2.89, 'Power': 99.8}, 'pv3': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}, 'pv4': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}}}
|
||||||
assert m.db.get_db_value(Register.VERSION) == 'V5.1.09'
|
assert m.db.get_db_value(Register.VERSION) == 'V5.1.09'
|
||||||
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
||||||
@@ -1903,8 +1907,8 @@ def test_msg_modbus_rsp3(config_tsun_inv1, msg_modbus_rsp21):
|
|||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.mb.err == 5
|
assert m.mb.err == 5
|
||||||
assert m.msg_count == 2
|
assert m.msg_count == 2
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp21
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp21
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.db == {'collector': {'Serial_Number': 'R170000000000001'}, 'inverter': {'Version': 'V5.1.0E', 'Rated_Power': 300}, 'grid': {'Timestamp': m._utc(), 'Voltage': 225.9, 'Current': 0.41, 'Frequency': 49.99, 'Output_Power': 94.8}, 'env': {'Inverter_Temp': 22}, 'input': {'Timestamp': m._utc(), 'pv1': {'Voltage': 0.8, 'Current': 0.0, 'Power': 0.0}, 'pv2': {'Voltage': 34.5, 'Current': 2.89, 'Power': 99.8}, 'pv3': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}, 'pv4': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}}}
|
assert m.db.db == {'collector': {'Serial_Number': 'R170000000000001'}, 'inverter': {'Version': 'V5.1.0E', 'Rated_Power': 300}, 'grid': {'Timestamp': m._utc(), 'Voltage': 225.9, 'Current': 0.41, 'Frequency': 49.99, 'Output_Power': 94.8}, 'env': {'Inverter_Temp': 22}, 'input': {'Timestamp': m._utc(), 'pv1': {'Voltage': 0.8, 'Current': 0.0, 'Power': 0.0}, 'pv2': {'Voltage': 34.5, 'Current': 2.89, 'Power': 99.8}, 'pv3': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}, 'pv4': {'Voltage': 0.0, 'Current': 0.0, 'Power': 0.0}}}
|
||||||
assert m.db.get_db_value(Register.VERSION) == 'V5.1.0E'
|
assert m.db.get_db_value(Register.VERSION) == 'V5.1.0E'
|
||||||
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
||||||
@@ -1932,9 +1936,9 @@ def test_msg_modbus_rsp4(config_tsun_inv1, msg_modbus_rsp21):
|
|||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
||||||
assert m.mb.err == 0
|
assert m.mb.err == 0
|
||||||
assert m.msg_count == 1
|
assert m.msg_count == 1
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp21
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp21
|
||||||
assert m.modbus_elms == 19
|
assert m.modbus_elms == 19
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.db == db_values
|
assert m.db.db == db_values
|
||||||
assert m.db.get_db_value(Register.VERSION) == 'V5.1.0E'
|
assert m.db.get_db_value(Register.VERSION) == 'V5.1.0E'
|
||||||
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
assert m.db.get_db_value(Register.TS_GRID) == m._utc()
|
||||||
@@ -1957,8 +1961,8 @@ def test_msg_modbus_rsp_new(config_tsun_inv1, msg_modbus_rsp20_new):
|
|||||||
assert m.msg_id==135
|
assert m.msg_id==135
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==107
|
assert m.data_len==107
|
||||||
assert m.ifc.forward.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -1977,8 +1981,8 @@ def test_msg_modbus_invalid(config_tsun_inv1, msg_modbus_inv):
|
|||||||
assert m.msg_id==119
|
assert m.msg_id==119
|
||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.data_len==13
|
assert m.data_len==13
|
||||||
assert m.ifc.forward.get()==msg_modbus_inv
|
assert m.ifc.fwd_fifo.get()==msg_modbus_inv
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
@@ -2006,8 +2010,8 @@ def test_msg_modbus_fragment(config_tsun_inv1, msg_modbus_rsp20):
|
|||||||
assert m.msg_id == 119
|
assert m.msg_id == 119
|
||||||
assert m.header_len == 23
|
assert m.header_len == 23
|
||||||
assert m.data_len == 50
|
assert m.data_len == 50
|
||||||
assert m.ifc.forward.get()==msg_modbus_rsp20
|
assert m.ifc.fwd_fifo.get()==msg_modbus_rsp20
|
||||||
assert m.ifc.write.get() == b''
|
assert m.ifc.tx_fifo.get() == b''
|
||||||
assert m.mb.err == 0
|
assert m.mb.err == 0
|
||||||
assert m.modbus_elms == 20-1 # register 0x300d is unknown, so one value can't be mapped
|
assert m.modbus_elms == 20-1 # register 0x300d is unknown, so one value can't be mapped
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
@@ -2021,15 +2025,15 @@ async def test_msg_build_modbus_req(config_tsun_inv1, msg_modbus_cmd):
|
|||||||
m.id_str = b"R170000000000001"
|
m.id_str = b"R170000000000001"
|
||||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||||
assert 0 == m.send_msg_ofs
|
assert 0 == m.send_msg_ofs
|
||||||
assert m.ifc.forward.get() == b''
|
assert m.ifc.fwd_fifo.get() == b''
|
||||||
assert m.ifc.write.get() == b''
|
assert m.ifc.tx_fifo.get() == b''
|
||||||
assert m.sent_pdu == b''
|
assert m.sent_pdu == b''
|
||||||
|
|
||||||
m.state = State.up
|
m.state = State.up
|
||||||
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
await m.send_modbus_cmd(Modbus.WRITE_SINGLE_REG, 0x2008, 0, logging.DEBUG)
|
||||||
assert 0 == m.send_msg_ofs
|
assert 0 == m.send_msg_ofs
|
||||||
assert m.ifc.forward.get() == b''
|
assert m.ifc.fwd_fifo.get() == b''
|
||||||
assert m.ifc.write.get() == b''
|
assert m.ifc.tx_fifo.get() == b''
|
||||||
assert m.sent_pdu == msg_modbus_cmd
|
assert m.sent_pdu == msg_modbus_cmd
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -2048,8 +2052,8 @@ def test_modbus_no_polling(config_no_modbus_poll, msg_get_time):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.data_len==0
|
assert m.data_len==0
|
||||||
assert m.ifc.forward.get()==msg_get_time
|
assert m.ifc.fwd_fifo.get()==msg_get_time
|
||||||
assert m.ifc.write.get()==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00\x1b\x10R170000000000001\x91"\x00\x00\x01\x89\xc6,_\x00'
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -2072,25 +2076,25 @@ async def test_modbus_polling(config_tsun_inv1, msg_inverter_ind):
|
|||||||
assert m.header_len==23
|
assert m.header_len==23
|
||||||
assert m.ts_offset==0
|
assert m.ts_offset==0
|
||||||
assert m.data_len==120
|
assert m.data_len==120
|
||||||
assert m.ifc.forward.get()==msg_inverter_ind
|
assert m.ifc.fwd_fifo.get()==msg_inverter_ind
|
||||||
assert m.ifc.write.get()==b'\x00\x00\x00\x14\x10R170000000000001\x99\x04\x01'
|
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00\x14\x10R170000000000001\x99\x04\x01'
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
||||||
|
|
||||||
m.ifc.write.clear() # clear send buffer for next test
|
m.ifc.tx_clear() # clear send buffer for next test
|
||||||
assert isclose(m.mb_timeout, 0.5)
|
assert isclose(m.mb_timeout, 0.5)
|
||||||
assert next(m.mb_timer.exp_count) == 0
|
assert next(m.mb_timer.exp_count) == 0
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x030\x00\x000J\xde'
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x03\x20\x00\x00`N"'
|
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x03\x20\x00\x00`N"'
|
||||||
assert m.ifc.write.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert next(m.mb_timer.exp_count) == 4
|
assert next(m.mb_timer.exp_count) == 4
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@@ -2133,3 +2137,15 @@ def test_multiiple_recv_buf(config_tsun_allow_all, multiple_recv_buf):
|
|||||||
assert m.db.stat['proxy']['Invalid_Data_Type'] == 1
|
assert m.db.stat['proxy']['Invalid_Data_Type'] == 1
|
||||||
|
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
|
def test_timeout(config_tsun_inv1):
|
||||||
|
_ = config_tsun_inv1
|
||||||
|
m = MemoryStream(b'')
|
||||||
|
assert m.state == State.init
|
||||||
|
assert Talent.MAX_START_TIME == m._timeout()
|
||||||
|
m.state = State.up
|
||||||
|
m.modbus_polling = True
|
||||||
|
assert Talent.MAX_INV_IDLE_TIME == m._timeout()
|
||||||
|
m.modbus_polling = False
|
||||||
|
assert Talent.MAX_DEF_IDLE_TIME == m._timeout()
|
||||||
|
m.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user