|
323 | 323 | @if (def.Id == "sfp-sgmiiplus" || def.Id == "sfp-sgmiiplus-port6") |
324 | 324 | { |
325 | 325 | <div class="alert alert-warning" style="margin-top: 0.75rem;"> |
326 | | - <strong>Compatibility note:</strong> Zyxel PMG3000-D20B support is currently being tested. If you have this module (or another GPON stick that may not negotiate 2.5 G cleanly with the UniFi host), feel free to try the patch, but be prepared to remove it if the link doesn't come up and stabilize. |
| 326 | + <strong>GPON stick compatibility:</strong> Some SFP GPON ONTs (particularly the Zyxel PMG3000-D20B) may not negotiate 2.5 G cleanly with the UniFi host without extra configuration. If your stick won't link up after deploying, <a href="javascript:void(0)" @onclick="() => _showZyxelInstructions = true" @onclick:stopPropagation="true" class="pt-inline-link">check these pre-flight steps</a>, and Remove the SFP tweak to restore the link if all else fails. |
327 | 327 | </div> |
328 | 328 | } |
329 | 329 |
|
|
524 | 524 | </div> |
525 | 525 | } |
526 | 526 |
|
| 527 | +<!-- GPON Stick Pre-Flight Instructions Modal --> |
| 528 | +@if (_showZyxelInstructions) |
| 529 | +{ |
| 530 | + <div class="pt-modal-overlay" @onclick="() => _showZyxelInstructions = false"> |
| 531 | + <div class="pt-modal pt-modal-wide" @onclick:stopPropagation="true"> |
| 532 | + <div class="pt-modal-header"> |
| 533 | + <h3>GPON Stick Compatibility - Pre-Flight Steps</h3> |
| 534 | + </div> |
| 535 | + <div class="pt-modal-body pt-instructions"> |
| 536 | + <p>Some GPON ONT SFP modules default to a link mode that won't negotiate 2.5 G with the UniFi host. If your stick doesn't link up after deploying the SGMII+ patch, you likely need to switch it to 2.5/1 G auto-negotiation mode first.</p> |
| 537 | + |
| 538 | + <p>The general process is:</p> |
| 539 | + <ol> |
| 540 | + <li>SSH into your SFP stick and configure it for 2.5/1 G auto-negotiation</li> |
| 541 | + <li>Deploy the SGMII+ patch from this page</li> |
| 542 | + <li>If it links up, persist the configuration so it survives SFP reboots</li> |
| 543 | + </ol> |
| 544 | + <p>The exact commands vary by stick. If yours isn't listed below, check your stick's documentation or community wiki for the equivalent auto-negotiation command.</p> |
| 545 | + |
| 546 | + <h4>If it doesn't work</h4> |
| 547 | + <p>If the link and data path don't come up after deploying, use the Remove button on the tweak card to unload the module - this should restore normal functionality. If the link still doesn't recover after removal, reboot the SFP stick.</p> |
| 548 | + |
| 549 | + <h4>Zyxel PMG3000-D20B</h4> |
| 550 | + |
| 551 | + <p><strong>Configure auto-negotiation.</strong> SSH to the stick and run:</p> |
| 552 | + <pre><code>linuxshell |
| 553 | +onu lanpcs 0 1 -1 4 15 1 0 5 0 0 1518 1 3 0 0 0</code></pre> |
| 554 | + <p>The <code>linuxshell</code> command breaks out of the Zyxel CLI into a Linux shell. The <code>onu lanpcs</code> command switches the SFP interface to 2.5/1 G auto-negotiation mode. It resets on SFP reboot, so you always have a way out.</p> |
| 555 | + |
| 556 | + <p><strong>Deploy the patch.</strong> Come back here and deploy the SGMII+ patch. After about a minute, the link should come up and you should have data path again.</p> |
| 557 | + |
| 558 | + <p><strong>Persist across reboots.</strong> If it works, make the command run automatically on every SFP boot. SSH to the stick again and run:</p> |
| 559 | + <pre><code># Enter the Linux shell first (if a new SSH session) |
| 560 | +linuxshell |
| 561 | + |
| 562 | +# Check if the boot script file already exists |
| 563 | +ls -la /var/config/run-syslog.sh</code></pre> |
| 564 | + |
| 565 | + <p>If the file <strong>does not exist</strong> (you see "No such file or directory"):</p> |
| 566 | + <pre><code>echo 'onu lanpcs 0 1 -1 4 15 1 0 5 0 0 1518 1 3 0 0 0' > /var/config/run-syslog.sh</code></pre> |
| 567 | + |
| 568 | + <p>If the file <strong>already exists</strong>, safely append the command:</p> |
| 569 | + <pre><code>grep -q 'lanpcs' /var/config/run-syslog.sh 2>/dev/null || echo 'onu lanpcs 0 1 -1 4 15 1 0 5 0 0 1518 1 3 0 0 0' >> /var/config/run-syslog.sh</code></pre> |
| 570 | + </div> |
| 571 | + <div class="pt-modal-footer"> |
| 572 | + <button class="btn btn-primary btn-sm" @onclick="() => _showZyxelInstructions = false">Got It</button> |
| 573 | + </div> |
| 574 | + </div> |
| 575 | + </div> |
| 576 | +} |
| 577 | + |
527 | 578 | <style> |
528 | 579 | .pt-container { |
529 | 580 | display: flex; |
|
723 | 774 | bottom: 0; |
724 | 775 | background: rgba(0, 0, 0, 0.6); |
725 | 776 | display: flex; |
726 | | - align-items: center; |
| 777 | + align-items: flex-start; |
727 | 778 | justify-content: center; |
728 | 779 | z-index: 1000; |
729 | | - padding: 1rem; |
| 780 | + padding: 2rem 1rem; |
| 781 | + overflow-y: auto; |
| 782 | + -webkit-overflow-scrolling: touch; |
730 | 783 | } |
731 | 784 |
|
732 | 785 | .pt-modal { |
733 | 786 | background: var(--bg-secondary); |
734 | 787 | border-radius: 0.75rem; |
735 | 788 | max-width: 540px; |
736 | 789 | width: 100%; |
| 790 | + margin: auto 0; |
737 | 791 | box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); |
738 | 792 | } |
739 | 793 |
|
|
800 | 854 | width: 100%; |
801 | 855 | } |
802 | 856 | } |
| 857 | +
|
| 858 | + /* Inline action link */ |
| 859 | + .pt-inline-link { |
| 860 | + color: var(--primary-color); |
| 861 | + text-decoration: underline; |
| 862 | + cursor: pointer; |
| 863 | + } |
| 864 | +
|
| 865 | + .pt-inline-link:hover { |
| 866 | + color: var(--primary-hover); |
| 867 | + } |
| 868 | +
|
| 869 | + /* Wide modal variant */ |
| 870 | + .pt-modal-wide { |
| 871 | + max-width: 640px; |
| 872 | + } |
| 873 | +
|
| 874 | + /* Instructional modal body */ |
| 875 | + .pt-instructions h4 { |
| 876 | + color: var(--text-primary); |
| 877 | + font-size: 0.95rem; |
| 878 | + margin: 1.25rem 0 0.5rem 0; |
| 879 | + } |
| 880 | +
|
| 881 | + .pt-instructions h4:first-child { |
| 882 | + margin-top: 0; |
| 883 | + } |
| 884 | +
|
| 885 | + .pt-instructions p { |
| 886 | + color: var(--text-secondary); |
| 887 | + font-size: 0.85rem; |
| 888 | + line-height: 1.5; |
| 889 | + margin: 0 0 0.5rem 0; |
| 890 | + } |
| 891 | +
|
| 892 | + .pt-instructions pre { |
| 893 | + background: var(--bg-primary); |
| 894 | + border-radius: 0.375rem; |
| 895 | + padding: 0.75rem 1rem; |
| 896 | + margin: 0.5rem 0 0.75rem 0; |
| 897 | + overflow-x: auto; |
| 898 | + } |
| 899 | +
|
| 900 | + .pt-instructions code { |
| 901 | + font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace; |
| 902 | + font-size: 0.8rem; |
| 903 | + color: var(--text-primary); |
| 904 | + } |
| 905 | +
|
| 906 | + .pt-instructions ol { |
| 907 | + color: var(--text-secondary); |
| 908 | + font-size: 0.85rem; |
| 909 | + line-height: 1.5; |
| 910 | + margin: 0 0 0.75rem 0; |
| 911 | + padding-left: 1.25rem; |
| 912 | + } |
| 913 | +
|
| 914 | + .pt-instructions li { |
| 915 | + margin-bottom: 0.25rem; |
| 916 | + } |
803 | 917 | </style> |
804 | 918 |
|
805 | 919 | @code { |
|
819 | 933 | private bool _confirmRisk; |
820 | 934 | private bool _showRemoveConfirm; |
821 | 935 | private string? _pendingRemoveTweakId; |
| 936 | + private bool _showZyxelInstructions; |
822 | 937 | private bool _allConfirmed => _confirmBackup && _confirmBackupDownloaded && _confirmWarranty && _confirmRisk; |
823 | 938 | private bool _canDeploy => _status?.UdmBootInstalled == true && _status?.FirmwareSupported == true; |
824 | 939 | private List<string> _deploySteps = new(); |
|
0 commit comments