diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml
index e2a15b2..0994c49 100644
--- a/.github/workflows/static.yml
+++ b/.github/workflows/static.yml
@@ -33,11 +33,13 @@ jobs:
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
- - name: Upload artifact
+
+ - name: Upload Artifact
uses: actions/upload-pages-artifact@v3
with:
- # Upload entire repository
- path: './UI'
+ # Deploy UI folder
+ path: './UI/'
+
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
diff --git a/UI/index.html b/UI/index.html
index 7fc2088..f892c33 100644
--- a/UI/index.html
+++ b/UI/index.html
@@ -40,8 +40,15 @@
@@ -124,7 +111,7 @@
diff --git a/UI/neodk.js b/UI/neodk.js
index fc1bc32..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,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
}
@@ -248,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);
@@ -358,6 +406,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:');
@@ -386,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);
}
@@ -484,6 +550,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 +582,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..f5899a0 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);
@@ -41,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);
@@ -52,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({
@@ -76,9 +129,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);
}