Source: components/system_settings/index.js

  1. import NumericSlider from "../../components/numeric_slider";
  2. import {useState, useEffect} from "preact/hooks";
  3. import {
  4. updateDeviceSettings,
  5. getDeviceSettings} from "../../utils/api";
  6. import {useConnectivity} from "../../context/online_context";
  7. import useInterval from "../../utils/use_interval";
  8. import SimpleChooser from '../../components/single_chooser';
  9. import { LabelSpinner } from '../../components/spinner';
  10. import RANGE_CONSTANTS from '../../utils/constants';
  11. import style from './style.css';
  12. /**
  13. * @brief Generates a UI element for changing NanoLux device system settings.
  14. */
  15. const SystemControls = () => {
  16. // Checks if the web app is connected to the device.
  17. const { isConnected } = useConnectivity();
  18. // Flag representing if initial data has been obtained from
  19. // the device.
  20. const [loading, setLoading] = useState(true);
  21. // Flag that tells the object to update the NanoLux device with new data.
  22. const [updated, setUpdated] = useState(false);
  23. // System settings data structure
  24. const [data, setData] = useState({
  25. length: 60,
  26. loop: 40,
  27. debug: 0
  28. });
  29. /**
  30. * @brief Manages initial querying of the data from the NanoLux device.
  31. * Sets the loading flag to false when done.
  32. */
  33. useEffect(() => {
  34. if (isConnected) {
  35. getDeviceSettings()
  36. .then(data => setData(data))
  37. .then(setLoading(false));
  38. }
  39. }, [isConnected])
  40. /**
  41. * @brief Updates the pattern on the Nanolux device
  42. * if it is connected and has modified data,
  43. * then flags the data structure.
  44. */
  45. useInterval(() => {
  46. if (isConnected && updated) {
  47. updateDeviceSettings(data);
  48. setUpdated(false);
  49. }
  50. }, 100);
  51. /**
  52. * @brief Updates a parameter in the subpattern data structure with a new value.
  53. * @param ref The string reference to update in the data structure
  54. * @param value The new value to update the data structure with
  55. */
  56. const update = (ref, value) => {
  57. if(!loading){
  58. setData((oldData) => {
  59. let newData = Object.assign({}, oldData);
  60. newData[ref] = value;
  61. return newData;
  62. })
  63. }
  64. setUpdated(true);
  65. }
  66. /**
  67. * @brief Generates the UI element for adjusting system settings.
  68. */
  69. return (
  70. (!loading ?
  71. <div>
  72. <NumericSlider
  73. className={style.settings_control}
  74. label="LED Strip Length"
  75. tooltip={{
  76. id: 'length',
  77. content: 'Adjusts how much of the LED strip is used by the device to display patterns',
  78. }}
  79. min={RANGE_CONSTANTS.LENGTH_MIN}
  80. max={RANGE_CONSTANTS.LENGTH_MAX}
  81. initial={data.length}
  82. structure_ref="length"
  83. update={update}
  84. />
  85. <br />
  86. <NumericSlider
  87. className={style.settings_control}
  88. label="LED Update Time (ms)"
  89. tooltip={{
  90. id: 'update',
  91. content: 'Adjusts how fast patterns are updated on the LED strip. Lower values mean patterns are updated faster.',
  92. }}
  93. min={RANGE_CONSTANTS.LOOP_MIN}
  94. max={RANGE_CONSTANTS.LOOP_MAX}
  95. initial={data.loop}
  96. structure_ref="loop"
  97. update={update}
  98. />
  99. <br />
  100. <SimpleChooser
  101. className={style.settings_control}
  102. label="Debug Mode"
  103. tooltip={{
  104. id: 'debug',
  105. content: 'Optional debugging modes for development.',
  106. }}
  107. options={[
  108. {option : "Debug Out", idx : 1, tooltip : "Prints pattern and strip data to the serial console for debugging."},
  109. {option : "Simulator Out", idx : 2, tooltip : "Prints full LED frames as comma-separated (R,G,B) values to the serial console for simulating patterns externally."},
  110. ]}
  111. noSelection={true}
  112. initial={data.debug}
  113. structure_ref="debug"
  114. update={update}
  115. />
  116. <br />
  117. </div>
  118. : <LabelSpinner />)
  119. );
  120. }
  121. export default SystemControls;