Fork of the excellent esp8266-react - https://github.com/rjwats/esp8266-react
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
3.7 KiB

  1. import React, { Component } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { SCAN_NETWORKS_ENDPOINT, LIST_NETWORKS_ENDPOINT } from '../constants/Endpoints';
  4. import SectionContent from '../components/SectionContent';
  5. import WiFiNetworkSelector from '../forms/WiFiNetworkSelector';
  6. import { withSnackbar } from 'notistack';
  7. import { redirectingAuthorizedFetch } from '../authentication/Authentication';
  8. const NUM_POLLS = 10
  9. const POLLING_FREQUENCY = 500
  10. const RETRY_EXCEPTION_TYPE = "retry"
  11. class WiFiNetworkScanner extends Component {
  12. constructor(props) {
  13. super(props);
  14. this.pollCount = 0;
  15. this.state = {
  16. scanningForNetworks: true,
  17. errorMessage: null,
  18. networkList: null
  19. };
  20. this.pollNetworkList = this.pollNetworkList.bind(this);
  21. this.requestNetworkScan = this.requestNetworkScan.bind(this);
  22. }
  23. componentDidMount() {
  24. this.scanNetworks();
  25. }
  26. requestNetworkScan() {
  27. const { scanningForNetworks } = this.state;
  28. if (!scanningForNetworks) {
  29. this.scanNetworks();
  30. }
  31. }
  32. scanNetworks() {
  33. this.pollCount = 0;
  34. this.setState({ scanningForNetworks: true, networkList: null, errorMessage: null });
  35. redirectingAuthorizedFetch(SCAN_NETWORKS_ENDPOINT).then(response => {
  36. if (response.status === 202) {
  37. this.schedulePollTimeout();
  38. return;
  39. }
  40. throw Error("Scanning for networks returned unexpected response code: " + response.status);
  41. }).catch(error => {
  42. this.props.enqueueSnackbar("Problem scanning: " + error.message, {
  43. variant: 'error',
  44. });
  45. this.setState({ scanningForNetworks: false, networkList: null, errorMessage: error.message });
  46. });
  47. }
  48. schedulePollTimeout() {
  49. setTimeout(this.pollNetworkList, POLLING_FREQUENCY);
  50. }
  51. retryError() {
  52. return {
  53. name: RETRY_EXCEPTION_TYPE,
  54. message: "Network list not ready, will retry in " + POLLING_FREQUENCY + "ms."
  55. };
  56. }
  57. compareNetworks(network1, network2) {
  58. if (network1.rssi < network2.rssi)
  59. return 1;
  60. if (network1.rssi > network2.rssi)
  61. return -1;
  62. return 0;
  63. }
  64. pollNetworkList() {
  65. redirectingAuthorizedFetch(LIST_NETWORKS_ENDPOINT)
  66. .then(response => {
  67. if (response.status === 200) {
  68. return response.json();
  69. }
  70. if (response.status === 202) {
  71. if (++this.pollCount < NUM_POLLS) {
  72. this.schedulePollTimeout();
  73. throw this.retryError();
  74. } else {
  75. throw Error("Device did not return network list in timely manner.");
  76. }
  77. }
  78. throw Error("Device returned unexpected response code: " + response.status);
  79. })
  80. .then(json => {
  81. json.networks.sort(this.compareNetworks)
  82. this.setState({ scanningForNetworks: false, networkList: json, errorMessage: null })
  83. })
  84. .catch(error => {
  85. if (error.name !== RETRY_EXCEPTION_TYPE) {
  86. this.props.enqueueSnackbar("Problem scanning: " + error.message, {
  87. variant: 'error',
  88. });
  89. this.setState({ scanningForNetworks: false, networkList: null, errorMessage: error.message });
  90. }
  91. });
  92. }
  93. render() {
  94. const { scanningForNetworks, networkList, errorMessage } = this.state;
  95. return (
  96. <SectionContent title="Network Scanner">
  97. <WiFiNetworkSelector scanningForNetworks={scanningForNetworks}
  98. networkList={networkList}
  99. errorMessage={errorMessage}
  100. requestNetworkScan={this.requestNetworkScan}
  101. selectNetwork={this.props.selectNetwork}
  102. />
  103. </SectionContent>
  104. )
  105. }
  106. }
  107. WiFiNetworkScanner.propTypes = {
  108. selectNetwork: PropTypes.func.isRequired
  109. };
  110. export default withSnackbar(WiFiNetworkScanner);