Skip to content

Commit b6ee0b8

Browse files
committed
Reverse engineer more of the API add max values and OPP settings
1 parent e0be4cf commit b6ee0b8

2 files changed

Lines changed: 161 additions & 45 deletions

File tree

assets/js/dp100.js

Lines changed: 89 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,26 @@ export function crc16 (buffer) {
2727

2828
/** DP100 Modbus Function IDs */
2929
const FUNCTIONS = Object.freeze({
30-
DEVICE_INFO: 0x10,
31-
FIRM_INFO: 17,
32-
START_TRANS: 18,
33-
DATA_TRANS: 19,
34-
END_TRANS: 20,
35-
DEV_UPGRADE: 21,
36-
BASIC_INFO: 48,
37-
BASIC_SET: 53,
38-
SYSTEM_INFO: 0x40,
39-
SYSTEM_SET: 69,
40-
SCAN_OUT: 80,
41-
SERIAL_OUT: 85,
42-
DISCONNECT: 0x80,
43-
NONE: 0xFF,
30+
DEVICE_INFO: 0x10, // 16
31+
FIRM_INFO: 0x11, // 17
32+
START_TRANS: 0x12, // 18
33+
DATA_TRANS: 0x13, // 19
34+
END_TRANS: 0x14, // 20
35+
DEV_UPGRADE: 0x15, // 21
36+
BASIC_INFO: 0x30, // 48
37+
BASIC_SET: 0x35, // 53
38+
SYSTEM_INFO: 0x40, // 64
39+
SYSTEM_SET: 0x45, // 69
40+
SCAN_OUT: 0x50, // 80
41+
SERIAL_OUT: 0x55, // 85
42+
DISCONNECT: 0x80, // 128
43+
NONE: 0xFF // 255
44+
})
45+
46+
const MAGIC_BYTES = Object.freeze({
47+
OUTPUT: 0x20, // 32
48+
SETTING: 0x40, // 64
49+
READ: 0x80 // 128
4450
})
4551

4652
/** DP100 device class.
@@ -87,6 +93,8 @@ export function DP100 (Base) {
8793
this.device = null
8894
clearInterval(this.updateLoop)
8995
})
96+
this.sendReport(FUNCTIONS.SYSTEM_INFO)
97+
this.sendReport(FUNCTIONS.DEVICE_INFO)
9098
this.getBasicSettings().then(() => {
9199
this.updateLoop = setInterval(() => {
92100
this.sendReport(FUNCTIONS.BASIC_INFO)
@@ -120,25 +128,39 @@ export function DP100 (Base) {
120128
}
121129

122130
async getBasicSettings () {
123-
await this.sendReport(FUNCTIONS.BASIC_SET, new Uint8Array([0 | 0x80]), 0)
131+
await this.sendReport(FUNCTIONS.BASIC_SET, new Uint8Array([MAGIC_BYTES.READ]), 0)
124132
}
125133

126-
async setBasicSettings ({ state, vo_set, io_set, ovp_set, ocp_set }) {
134+
async setBasicOutput ({ state, vo_set, io_set }) {
127135
if (this.settings === undefined) {
128136
throw new Error('Settings not loaded')
129137
}
130-
console.info('setBasicSettings', { state, vo_set, io_set, ovp_set, ocp_set })
138+
console.info('setBasicOutput', { state, vo_set, io_set })
131139
const basicSet = Object.assign({}, this.settings, Object.fromEntries(Object.entries({
132-
state, vo_set, io_set, ovp_set, ocp_set
140+
state, vo_set, io_set
133141
}).filter(([k, v]) => v !== undefined)))
134-
const index = this.settingsQueue.length
135-
this.settingsQueue[index] = basicSet
142+
this.settingsQueue.push(basicSet)
136143
const out = new Uint8Array(10)
137144
const outDv = new DataView(out.buffer, out.byteOffset, out.length)
138-
outDv.setUint8(0, index | 0x20)
145+
outDv.setUint8(0, MAGIC_BYTES.OUTPUT)
139146
outDv.setUint8(1, basicSet.state)
140147
outDv.setUint16(2, basicSet.vo_set * 1000, true)
141148
outDv.setUint16(4, basicSet.io_set * 1000, true)
149+
await this.sendReport(FUNCTIONS.BASIC_SET, out, 0)
150+
}
151+
152+
async setBasicSettings ({ ovp_set, ocp_set }) {
153+
if (this.settings === undefined) {
154+
throw new Error('Settings not loaded')
155+
}
156+
console.info('setBasicSettings', { ovp_set, ocp_set })
157+
const basicSet = Object.assign({}, this.settings, Object.fromEntries(Object.entries({
158+
ovp_set, ocp_set
159+
}).filter(([k, v]) => v !== undefined)))
160+
this.settingsQueue.push(basicSet)
161+
const out = new Uint8Array(10)
162+
const outDv = new DataView(out.buffer, out.byteOffset, out.length)
163+
outDv.setUint8(0, MAGIC_BYTES.SETTING)
142164
outDv.setUint16(6, basicSet.ovp_set * 1000, true)
143165
outDv.setUint16(8, basicSet.ocp_set * 1000, true)
144166
await this.sendReport(FUNCTIONS.BASIC_SET, out, 0)
@@ -181,21 +203,44 @@ export function DP100 (Base) {
181203
})
182204
break
183205
case FUNCTIONS.BASIC_SET:
184-
if (contentView.byteLength === 1) {
185-
this.settings = this.settingsQueue.pop(contentView.getUint8(0))
206+
if (contentView.byteLength === 1 && contentView.getUint8(0)) {
207+
this.settings = this.settingsQueue.pop()
186208
break
187209
}
188210
this.receiveBasicSettings({
189-
index: contentView.getUint8(0),
211+
ack: contentView.getUint8(0),
190212
state: contentView.getUint8(1),
191213
vo_set: contentView.getUint16(2, true) / 1000,
192214
io_set: contentView.getUint16(4, true) / 1000,
193215
ovp_set: contentView.getUint16(6, true) / 1000,
194216
ocp_set: contentView.getUint16(8, true) / 1000,
195217
})
196218
break
219+
case FUNCTIONS.SYSTEM_INFO:
220+
this.receiveSystemInfo({
221+
otp: contentView.getUint16(0, true),
222+
opp: contentView.getUint16(2, true) / 10.0,
223+
backlight: contentView.getUint8(4),
224+
volume: contentView.getUint8(5),
225+
reverse_protection: contentView.getUint8(6),
226+
audio_out: contentView.getUint8(7),
227+
})
228+
break
229+
case FUNCTIONS.DEVICE_INFO:
230+
console.debug({
231+
deviceName: String.fromCharCode(...new Uint8Array(contentView.buffer.slice(0, 15))),
232+
hardwareVersion: contentView.getUint16(16, true) / 10,
233+
firmwareVersion: contentView.getUint16(18, true) / 10,
234+
bootVersion: contentView.getUint16(20, true),
235+
runVersion: contentView.getUint16(22, true),
236+
serialNumber: new Uint8Array(contentView.buffer.slice(24, 24 + 11)).join(''),
237+
year: contentView.getUint16(36, true),
238+
month: contentView.getUint8(38),
239+
day: contentView.getUint8(39),
240+
})
241+
break
197242
default:
198-
console.warn('Unhandled function', header.functionType)
243+
console.warn('Unhandled function', header.functionType, contentView)
199244
}
200245
}
201246

@@ -218,16 +263,31 @@ export function DP100 (Base) {
218263

219264
/** Handle basic settings from the DP100
220265
* @param {Object} basicSettings
221-
* @param {Number} basicSettings.index - Setting index.
222-
* @param {Number} basicSettings.state - Setting state.
266+
* @param {boolean} basicSettings.ack - Acknowledgement.
267+
* @param {boolean} basicSettings.state - Setting state.
223268
* @param {Number} basicSettings.vo_set - Output voltage setting in V.
224269
* @param {Number} basicSettings.io_set - Output current setting in A.
225270
* @param {Number} basicSettings.ovp_set - Over-voltage protection setting in V.
226271
* @param {Number} basicSettings.ocp_set - Over-current protection setting in A.
227272
*/
228-
receiveBasicSettings ({ index, state, vo_set, io_set, ovp_set, ocp_set }) {
229-
console.info('receiveBasicSettings', { index, state, vo_set, io_set, ovp_set, ocp_set })
273+
receiveBasicSettings ({ ack, state, vo_set, io_set, ovp_set, ocp_set }) {
274+
console.info('receiveBasicSettings', { ack, state, vo_set, io_set, ovp_set, ocp_set })
230275
this.settings = { state, vo_set, io_set, ovp_set, ocp_set }
231276
}
277+
278+
/** Handle system info from the DP100
279+
* @param {Object} system
280+
* @param {Number} system.backlight - Backlight setting between 0 and 4.
281+
* @param {Number} system.volume - Volume setting between 0 and 4.
282+
* @param {Number} system.opp - Over-power protection setting in W.
283+
* @param {Number} system.otp - Over-temperature protection setting in C (range: 50 – 80).
284+
* @param {boolean} system.reverse_protection - Reverse protection setting.
285+
* @param {boolean} system.audio_out - Audio output setting.
286+
*/
287+
receiveSystemInfo ({ backlight, volume, opp, otp, reverse_protection, audio_out }) {
288+
console.info('receiveSystemInfo', { backlight, volume, opp, otp, reverse_protection, audio_out })
289+
this.system = { backlight, volume, opp, otp, reverse_protection, audio_out }
290+
}
291+
232292
}
233293
}

assets/js/ui.js

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,15 @@ export class DP100Element extends DP100(LitElement) {
8585
tHistory = []
8686
vHistory = []
8787
iHistory = []
88-
wHistory = []
88+
pHistory = []
8989

9090
static properties = {
9191
device: { type: Object, attribute: false, reflect: true },
9292
settings: { type: Object, attribute: false, reflect: true },
93-
info: { type: Object, attribute: false, reflect: true }
93+
info: { type: Object, attribute: false, reflect: true },
94+
vMax: { type: Number, attribute: false, reflect: true },
95+
iMax: { type: Number, attribute: false, reflect: true },
96+
pMax: { type: Number, attribute: false, reflect: true },
9497
}
9598
static styles = css`
9699
:host {
@@ -162,7 +165,7 @@ export class DP100Element extends DP100(LitElement) {
162165
grid-area: graph;
163166
border: thick solid CanvasText;
164167
}
165-
168+
166169
#vOut, #iOut, #pOut {
167170
font-size: 2em;
168171
display: flex;
@@ -229,6 +232,13 @@ export class DP100Element extends DP100(LitElement) {
229232
}
230233
`
231234

235+
constructor () {
236+
super()
237+
this.vMax = 0
238+
this.iMax = 0
239+
this.pMax = 0
240+
}
241+
232242
render () {
233243
return html`
234244
<link href="https://cdn.jsdelivr.net/npm/uplot@1.6.31/dist/uPlot.min.css" rel="stylesheet">
@@ -259,6 +269,16 @@ export class DP100Element extends DP100(LitElement) {
259269
max="${this.info?.voMax}" step="0.1">
260270
</div>
261271
</div>
272+
<div class="group">
273+
<div class="label">
274+
V<sub>max</sub>
275+
</div>
276+
<div class="value-1">
277+
${(this.vMax).toLocaleString(undefined, { minimumFractionDigits: 3 })}
278+
</div>
279+
<div class="value-2">
280+
</div>
281+
</div>
262282
</div>
263283
<div id="iOut">
264284
<div class="group">
@@ -286,31 +306,55 @@ export class DP100Element extends DP100(LitElement) {
286306
max="5" step="0.1">
287307
</div>
288308
</div>
309+
<div class="group">
310+
<div class="label">
311+
A<sub>max</sub>
312+
</div>
313+
<div class="value-1">
314+
${(this.iMax).toLocaleString(undefined, { minimumFractionDigits: 3 })}
315+
</div>
316+
<div class="value-2">
317+
</div>
318+
</div>
289319
</div>
290320
<div id="pOut">
291321
<div class="group">
292322
<div class="label">
293323
W<sub>out</sub>
294324
</div>
295325
<div class="value-1">
326+
${(this.info?.iOut * this.info?.vOut).toLocaleString(undefined, { minimumFractionDigits: 3 })}
327+
</div>
328+
<div class="value-2">
329+
</div>
330+
</div>
331+
<div class="group">
332+
<div class="label">
333+
W<sub>max</sub>
334+
</div>
335+
<div class="value-1">
336+
${(this.pMax).toLocaleString(undefined, { minimumFractionDigits: 3 })}
296337
</div>
297338
<div class="value-2">
298-
${(this.info?.iOut * this.info?.vOut).toLocaleString(undefined, { minimumFractionDigits: 3 })}
299339
</div>
300340
</div>
301341
</div>
302342
<div id="mode">
303343
${this.renderMode()}
304344
</div>
305345
<div id="opp" class="group">
306-
<div class="label"></div>
346+
<div class="label">OPP</div>
307347
<div class="value-1">
308-
OVP
309-
${this.settings?.ovp_set.toLocaleString(undefined, { minimumFractionDigits: 3 })}&numsp;V
348+
V
349+
<input type="number" @change=${this.changeOverVoltageProtection.bind(this)}
350+
.value=${this.settings?.ovp_set} min="0"
351+
max="30.5" step="0.01">
310352
</div>
311353
<div class="value-2">
312-
OCP
313-
${this.settings?.ocp_set.toLocaleString(undefined, { minimumFractionDigits: 3 })}&numsp;A
354+
A
355+
<input type="number" @change=${this.changeOverCurrentProtection.bind(this)}
356+
.value=${this.settings?.ocp_set} min="0"
357+
max="5.05" step="0.001">
314358
</div>
315359
</div>
316360
<div id="vInMax" class="group">
@@ -367,15 +411,23 @@ export class DP100Element extends DP100(LitElement) {
367411
}
368412

369413
togglePower () {
370-
this.setBasicSettings({ state: this.settings.state ? 0 : 1 })
414+
this.setBasicOutput({ state: this.settings.state ? 0 : 1 })
371415
}
372416

373417
changeVoltage (event) {
374-
this.setBasicSettings({ vo_set: event.target.value })
418+
this.setBasicOutput({ vo_set: event.target.value })
375419
}
376420

377421
changeCurrent (event) {
378-
this.setBasicSettings({ io_set: event.target.value })
422+
this.setBasicOutput({ io_set: event.target.value })
423+
}
424+
425+
changeOverVoltageProtection (event) {
426+
this.setBasicSettings({ ovp_set: event.target.value })
427+
}
428+
429+
changeOverCurrentProtection (event) {
430+
this.setBasicSettings({ ocp_set: event.target.value })
379431
}
380432

381433
firstUpdated () {
@@ -384,23 +436,27 @@ export class DP100Element extends DP100(LitElement) {
384436
...grapOptions,
385437
width: graphElement.offsetWidth,
386438
height: graphElement.offsetHeight - 48,
387-
}, [this.tHistory, this.vHistory, this.iHistory, this.wHistory], graphElement)
439+
}, [this.tHistory, this.vHistory, this.iHistory, this.pHistory], graphElement)
388440
}
389441

390442
receiveBasicInfo ({ vIn, vOut, iOut, voMax, temp1, temp2, dc5V, outMode, workSt }) {
391443
super.receiveBasicInfo({ vIn, vOut, iOut, voMax, temp1, temp2, dc5V, outMode, workSt })
392444

445+
this.vMax = vOut > this.vMax ? vOut : this.vMax
446+
this.iMax = iOut > this.iMax ? iOut : this.iMax
447+
this.pMax = vOut * iOut > this.pMax ? vOut * iOut : this.pMax
448+
393449
this.tHistory.push(Date.now() / 1000) // uplot uses seconds
394450
this.vHistory.push(vOut)
395451
this.iHistory.push(iOut)
396-
this.wHistory.push(vOut * iOut)
452+
this.pHistory.push(vOut * iOut)
397453
if (this.vHistory.length > 30 * 1000 / this.refreshRate) {
398454
this.tHistory.shift()
399455
this.vHistory.shift()
400456
this.iHistory.shift()
401-
this.wHistory.shift()
457+
this.pHistory.shift()
402458
}
403-
this.graph.setData([this.tHistory, this.vHistory, this.iHistory, this.wHistory])
459+
this.graph.setData([this.tHistory, this.vHistory, this.iHistory, this.pHistory])
404460
}
405461
}
406462

0 commit comments

Comments
 (0)