From febae82b29c438f04cd0dc92a0bfe7f514276195 Mon Sep 17 00:00:00 2001 From: edger477 Date: Wed, 20 Nov 2024 14:21:04 +0100 Subject: [PATCH 1/6] added battery voltage --- UI/index.html | 24 ++------------------- UI/neodk.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++--- UI/script.js | 37 +++++++++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 27 deletions(-) diff --git a/UI/index.html b/UI/index.html index 7fc2088..d9bf99b 100644 --- a/UI/index.html +++ b/UI/index.html @@ -41,7 +41,7 @@

NeoDK control panel

- NeoDK ({{ device.state.PlayState }} | {{ device.state.Intensity }}% )

+ NeoDK ({{ device.state.PlayState }} | {{ device.state.Intensity }}% ) | Battery Voltage: {{ device.state.power.BatteryVoltage }}V
@@ -54,26 +54,6 @@

{{ device.state.Intensity }}

- -
 
@@ -124,7 +104,7 @@

Pattern: {{ device.state.CurrentPattern }} diff --git a/UI/neodk.js b/UI/neodk.js index fc1bc32..74d2c94 100644 --- a/UI/neodk.js +++ b/UI/neodk.js @@ -76,6 +76,10 @@ class NeoDK { this.#sendAttrWriteRequest(this.#the_writer, NeoDK.#AttributeId.IntensityPercent, new Uint8Array([NeoDK.#Encoding.UnsignedInt1, intensity])); } + refreshVoltages(){ + this.#sendAttrReadRequest(this.#the_writer, NeoDK.#AttributeId.Voltages); + } + /** * Method to get the port from browser * User will be prompted to select a port that box is connected to @@ -102,16 +106,49 @@ class NeoDK { return await this.#usePort(port); } + static BoxPower = class NeoDKBoxPower { + /** + * + */ + constructor() { + this._batteryVoltage = 0; + this._capacitorVoltage = 0; + this._primaryCurrent = 0; + } + + get BatteryVoltage() { + return this._batteryVoltage; + } + set BatteryVoltage(value) { + this._batteryVoltage = value; + } + + get CapacitorVoltage() { + return this._capacitorVoltage; + } + set CapacitorVoltage(value) { + this._capacitorVoltage = value; + } + + get PrimaryCurrent() { + return this._primaryCurrent; + } + set PrimaryCurrent(value) { + this._primaryCurrent = value; + } + + } /** * Structure that represents play state of NeoDK */ - static State = class { + static State = class NeoDKState { constructor() { this._playState = NeoDK.#playStates[0]; this._intensity = 0; this._currentPattern = ''; this._availablePatterns = []; + this.power = new NeoDK.BoxPower(); } @@ -190,10 +227,12 @@ class NeoDK { * @readonly */ static #AttributeId = { + Voltages: 3, AllPatternNames: 5, CurrentPatternName: 6, IntensityPercent: 7, - PlayPauseStop: 8 + PlayPauseStop: 8, + BoxName: 9 }; /** @@ -205,6 +244,7 @@ class NeoDK { static #Encoding = { UnsignedInt1: 4, UTF8_1Len: 12, + Bytes_1Len: 16, Array: 22, EndOfContainer: 24 } @@ -358,6 +398,17 @@ class NeoDK { let offset = NeoDK.#StructureSize.AttributeAction; const data_length = aa.length - offset; switch (attribute_id) { + case NeoDK.#AttributeId.Voltages: + if (data_length >= 8 && aa[offset] == NeoDK.#Encoding.Bytes_1Len) { + const Vbat_mV = aa[offset + 2] | ((aa[offset + 3]) << 8); + const Vcap_mV = aa[offset + 4] | ((aa[offset + 5]) << 8); + const Ipri_mA = aa[offset + 6] | ((aa[offset + 7]) << 8); + this.state.power.BatteryVoltage = Vbat_mV / 1000; + this.state.power.CapacitorVoltage = Vcap_mV / 1000; + this.state.power.PrimaryCurrent = Ipri_mA / 1000; + this.logger.log('Vbat=' + Vbat_mV + ' mV, Vcap=' + Vcap_mV + ' mV, Ipri=' + Ipri_mA + ' mA'); + } + break; case NeoDK.#AttributeId.AllPatternNames: if (data_length >= 2 && aa[offset] == NeoDK.#Encoding.Array) { this.logger.log('Available patterns:'); @@ -484,6 +535,8 @@ class NeoDK { // We have one readable attribute and three we can subscribe to. this.#sendAttrReadRequest(this.#the_writer, NeoDK.#AttributeId.AllPatternNames); + this.#sendAttrReadRequest(this.#the_writer, NeoDK.#AttributeId.Voltages); + this.#sendAttrReadRequest(this.#the_writer, NeoDK.#AttributeId.BoxName); this.#sendAttrSubscribeRequest(this.#the_writer, NeoDK.#AttributeId.CurrentPatternName); this.#sendAttrSubscribeRequest(this.#the_writer, NeoDK.#AttributeId.IntensityPercent); this.#sendAttrSubscribeRequest(this.#the_writer, NeoDK.#AttributeId.PlayPauseStop); @@ -514,4 +567,5 @@ class NeoDK { } } -export default NeoDK; \ No newline at end of file +export default NeoDK; + diff --git a/UI/script.js b/UI/script.js index 62bca46..8730fe0 100644 --- a/UI/script.js +++ b/UI/script.js @@ -1,9 +1,42 @@ import NeoDK from './neodk.js'; import { createApp, ref, toRaw, computed } from 'vue'; +class NeoDKBoxPowerVM extends NeoDK.BoxPower { + constructor() { + super(); + + } + + #batteryVoltage = ref(super._batteryVoltage); + #capacitorVoltage = ref(super._capacitorVoltage); + #primaryCurrent = ref(super._primaryCurrent); + + get BatteryVoltage() { + return toRaw(this).#batteryVoltage.value; + } + set BatteryVoltage(value){ + toRaw(this).#batteryVoltage.value = value; + } + + get CapacitorVoltage() { + return toRaw(this).#capacitorVoltage.value; + } + set CapacitorVoltage(value){ + toRaw(this).#capacitorVoltage.value = value; + } + + get PrimaryCurrent() { + return toRaw(this).#primaryCurrent.value; + } + set PrimaryCurrent(value){ + toRaw(this).#primaryCurrent.value = value; + } +} + class NeoDKStateVM extends NeoDK.State { constructor() { super(); + this.power = new NeoDKBoxPowerVM(); } #playState = ref(super._playState); @@ -76,9 +109,9 @@ const app = createApp({ async refreshState() { try { this.devices.forEach(element => { - // todo add anything that needs to be periodically refreshed here + toRaw(element).refreshVoltages(); }); - //setTimeout(this.refreshState, 1000); + setTimeout(this.refreshState, 1000 * 60 * 5); } catch (error) { console.error('Failed to fetch state', error); } From ce4e892dd1bb38dbbecc35a6ab391823c0da01d8 Mon Sep 17 00:00:00 2001 From: edger477 <101211585+edger477@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:30:11 +0100 Subject: [PATCH 2/6] Update static.yml to deploy only UI --- .github/workflows/static.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index e2a15b2..7712d02 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -36,8 +36,8 @@ jobs: - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - # Upload entire repository - path: './UI' + # Upload UI directory + path: 'UI/' - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 From 39e37400bfcc660d29f617c7fd6e5bcb0ca8af01 Mon Sep 17 00:00:00 2001 From: edger477 <101211585+edger477@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:38:37 +0100 Subject: [PATCH 3/6] Update static.yml --- .github/workflows/static.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 7712d02..8b44b99 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -33,11 +33,17 @@ jobs: uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v5 - - name: Upload artifact + - name: Move Files to Root + run: | + mv UI/* ./ + mv UI/.* ./ || true + + - name: Upload Artifact uses: actions/upload-pages-artifact@v3 with: - # Upload UI directory - path: 'UI/' + # Deploy only the files moved to root + path: './' + - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 From 483fafd6e6ea8d3dd588f16107d281269d0dc7e0 Mon Sep 17 00:00:00 2001 From: edger477 <101211585+edger477@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:41:16 +0100 Subject: [PATCH 4/6] Update static.yml --- .github/workflows/static.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 8b44b99..149eac5 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -33,16 +33,12 @@ jobs: uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v5 - - name: Move Files to Root - run: | - mv UI/* ./ - mv UI/.* ./ || true - name: Upload Artifact uses: actions/upload-pages-artifact@v3 with: - # Deploy only the files moved to root - path: './' + # Deploy UI folder + path: './UI' - name: Deploy to GitHub Pages id: deployment From 67a9cfc723d05df0bc7224c0bdc5727818cc77b8 Mon Sep 17 00:00:00 2001 From: edger477 <101211585+edger477@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:41:27 +0100 Subject: [PATCH 5/6] Update static.yml --- .github/workflows/static.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 149eac5..0994c49 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -38,7 +38,7 @@ jobs: uses: actions/upload-pages-artifact@v3 with: # Deploy UI folder - path: './UI' + path: './UI/' - name: Deploy to GitHub Pages id: deployment From c59ab1fc329e0ec3c60df04dd887a74177fa185d Mon Sep 17 00:00:00 2001 From: edger477 Date: Wed, 20 Nov 2024 16:23:51 +0100 Subject: [PATCH 6/6] added box name support --- UI/index.html | 11 +++++++++-- UI/neodk.js | 37 ++++++++++++++++++++++++++----------- UI/script.js | 20 ++++++++++++++++++++ 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/UI/index.html b/UI/index.html index d9bf99b..f892c33 100644 --- a/UI/index.html +++ b/UI/index.html @@ -40,8 +40,15 @@

NeoDK control panel

-

- NeoDK ({{ device.state.PlayState }} | {{ device.state.Intensity }}% ) | Battery Voltage: {{ device.state.power.BatteryVoltage }}V

+

+ {{ device.Name || "(no name)"}} + |

+

+ +

+

+

({{ device.state.PlayState }} | {{ device.state.Intensity }}% )

+
Battery Voltage: {{ device.state.power.BatteryVoltage }}V
diff --git a/UI/neodk.js b/UI/neodk.js index 74d2c94..41e2660 100644 --- a/UI/neodk.js +++ b/UI/neodk.js @@ -19,6 +19,7 @@ class NeoDK { this.logger = logger; this.state = state; + this._name = ''; } /** @@ -41,17 +42,20 @@ class NeoDK { // Public methods + get Name() { + return this._name; + } + set Name(value) { + this._name = value; + this.#writeString(value, NeoDK.#AttributeId.BoxName) + } /** * Method to select pattern to play * @public * @param {string} name name of the pattern to select */ selectPattern(name) { - let enc_name = new TextEncoder().encode(name); - const array = Array.from(enc_name); // Convert to regular array - array.unshift(NeoDK.#Encoding.UTF8_1Len, enc_name.length); // Use unshift - enc_name = Uint8Array.from(array); - this.#sendAttrWriteRequest(this.#the_writer, NeoDK.#AttributeId.CurrentPatternName, enc_name); + this.#writeString(name, NeoDK.#AttributeId.CurrentPatternName); } /** @@ -60,11 +64,7 @@ class NeoDK { * @param {ChangeStateCommand} state one of the accepted play states from ChangeStateCommand */ setPlayState(state) { - let enc_state = new TextEncoder().encode(state); - const array = Array.from(enc_state); // Convert to regular array - array.unshift(NeoDK.#Encoding.UTF8_1Len, enc_state.length); // Use unshift - enc_state = Uint8Array.from(array); - this.#sendAttrWriteRequest(this.#the_writer, NeoDK.#AttributeId.PlayPauseStop, enc_state); + this.#writeString(state, NeoDK.#AttributeId.PlayPauseStop); } /** @@ -76,7 +76,7 @@ class NeoDK { this.#sendAttrWriteRequest(this.#the_writer, NeoDK.#AttributeId.IntensityPercent, new Uint8Array([NeoDK.#Encoding.UnsignedInt1, intensity])); } - refreshVoltages(){ + refreshVoltages() { this.#sendAttrReadRequest(this.#the_writer, NeoDK.#AttributeId.Voltages); } @@ -288,6 +288,14 @@ class NeoDK { // private methods + #writeString(value, attribute) { + let enc_value = new TextEncoder().encode(value); + const array = Array.from(enc_value); // Convert to regular array + array.unshift(NeoDK.#Encoding.UTF8_1Len, enc_value.length); // Use unshift + enc_value = Uint8Array.from(array); + this.#sendAttrWriteRequest(this.#the_writer, attribute, enc_value); + } + #initFrame(payload_size, frame_type, service_type, seq) { const frame = new Uint8Array(NeoDK.#StructureSize.FrameHeader + payload_size); frame[0] = (service_type << 4) | (frame_type << 1); @@ -437,6 +445,13 @@ class NeoDK { this.logger.log('NeoDK is ' + NeoDK.#playStates[play_state]); } break; + case NeoDK.#AttributeId.BoxName: + if (aa[offset] == NeoDK.#Encoding.UTF8_1Len) { + const name = new TextDecoder().decode(aa.slice(offset + 2)); + this._name = name; + this.logger.log('Box name is ' + name); + } + break; default: this.logger.log('Unexpected attribute id: ' + attribute_id); } diff --git a/UI/script.js b/UI/script.js index 8730fe0..f5899a0 100644 --- a/UI/script.js +++ b/UI/script.js @@ -74,6 +74,16 @@ class NeoDKStateVM extends NeoDK.State { } class NeoDKVM extends NeoDK { + + /** + * + */ + constructor(...args) { + super(...args); + this.changingName = ref(false); + this.newName = ''; + } + setIntensity = (intensity) => super.setIntensity(intensity); selectPattern = (pattern) => super.selectPattern(pattern); @@ -85,6 +95,16 @@ class NeoDKVM extends NeoDK { stop = () => super.setPlayState(NeoDK.ChangeStateCommand.stop); paused = computed(() => ['paused', 'stopped'].includes(this.state.PlayState)); + + changeName = () => { + this.changingName.value = true; + this.newName = this.Name; + } + + saveName = () => { + this.Name = this.newName; + this.changingName.value = false; + } } const app = createApp({