Hi There,
Have spent a chunk of time today googling around and trying things, @Troon seemed to be fairly knowledgable on this subject and helped others with a similar issue.
The Arcam AVR41 device hosts a web interface, 1 of the pages contains a value named “Incoming format” which I would like to create a sensor for and have it shown on a dashboard, picture of web page with value below:
Using the Dev Tools it appears when going to the “General setup” tab on the main page of the AV41 there is a HTML and .js url that is called, I recall @Troon explaining that the HTML is called first, then .js is called to retrieve the values and feeds them back into the HTML. The two URL’s it calls are below
http://192.168.0.71/setup/general-setup.html?_=1737077536545
http://192.168.0.71/setup/public/js/general-setup.js?_=1737077536546
I know the “arcam_fmj” integration exists however that is coded to only read the “Decode Mode” which is not the information I am after, I wonder if @elupus may be open to adding in the ability to read the “Incoming format” value ?
Both HTML/.js content below, I did manage to create a scrape sensor however that only calls/reads the static html which has a dummy value inside it which is simply “—”, would it be possible to get any help with this?
<form class="pt-5">
<div class="form-group row">
<label for="source-input" class="col-3 col-form-label">Source Input</label>
<div class="col-8">
<input id="source-input" name="source-input" type="text" class="form-control here" value="CD" disabled>
</div>
</div>
<div class="form-group row">
<label for="incoming-format" class="col-3 col-form-label">Incoming format</label>
<div class="col-8">
<input id="incoming-format" name="incoming-format" type="text" class="form-control here" value="---" disabled>
</div>
</div>
<div class="form-group row">
<label for="incoming-sample-rate" class="col-3 col-form-label">Incoming sample rate</label>
<div class="col-8">
<input id="incoming-sample-rate" name="incoming-sample-rate" type="text" class="form-control here" value="---" disabled>
</div>
</div>
<div class="form-group row">
<label for="incoming-bitrate" class="col-3 col-form-label">Incoming bitrate</label>
<div class="col-8">
<input id="incoming-bitrate" name="incoming-bitrate" type="text" class="form-control here" value="---" disabled>
</div>
</div>
<div class="form-group row">
<label for="dialnorm" class="col-3 col-form-label">Dialnorm</label>
<div class="col-8">
<input id="dialnorm" name="dialnorm" type="text" class="form-control here" value="---" disabled>
</div>
</div>
<div class="form-group row">
<label for="incoming-video-resolution" class="col-3 col-form-label">Incoming video format</label>
<div class="col-8">
<input id="incoming-video-resolution" name="incoming-video-resolution" type="text" class="form-control here" value="---" disabled>
</div>
</div>
<div class="form-group row">
<label for="audio-compression" class="col-3 col-form-label">Audio compression</label>
<div class="col-8">
<select id="audio-compression" name="audio-compression" class="custom-select">
<option value="0" selected>Off</option>
<option value="1">Medium</option>
<option value="2">High</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="balance" class="col-3 col-form-label">Balance</label>
<div class="col-8">
<div class="row">
<div class="col">
<input id="balance" name="balance" type="range" min="-6" max="6" step="1" class="custom-range form-control here d-none d-md-block" value="0">
<div class="row h-100">
<div class="col text-secondary d-none d-md-block">Left +6dB</div>
<output name="balance" id="balance" class="col text-left text-md-center my-auto my-md-0">0dB</output>
<div class="col text-right text-secondary d-none d-md-block">Right +6dB</div>
</div>
</div>
<div class="col-auto">
<button id="decrease-balance" aria-label="balance decrease" type="button" class="btn btn-secondary stepper" aria-label="Decrease Balance">
<i class="fas fa-minus"></I>
</button>
<button id="increase-balance" aria-label="balance increase" type="button" class="btn btn-secondary stepper" aria-label="Increase Balance">
<i class="fas fa-plus"></I>
</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label for="dts-dialogue-control" class="col-3 col-form-label">DTS Dialogue Control</label>
<div class="col-8">
<div class="row">
<div class="col">
<input id="dts-dialogue-control" name="dts-dialogue-control" type="range" min="0" max="6" step="1" class="custom-range form-control here d-none d-md-block" value="0">
<div class="row h-100">
<div class="col text-secondary d-none d-md-block">0dB</div>
<output name="dts-dialogue-control" id="dts-dialogue-control" class="col text-left text-md-center my-auto my-md-0">0dB</output>
<div class="col text-right text-secondary d-none d-md-block">+6dB</div>
</div>
</div>
<div class="col-auto">
<button id="decrease-dts-dialogue-control" aria-label="DTS dialogue decrease" type="button" class="btn btn-secondary stepper" aria-label="Decrease DTS Dialogue Control">
<i class="fas fa-minus"></I>
</button>
<button id="increase-dts-dialogue-control" aria-label="DTS dialogue increase" type="button" class="btn btn-secondary stepper" aria-label="Increase DTS Dialogue Control">
<i class="fas fa-plus"></I>
</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label for="maximum-volume" class="col-3 col-form-label">Maximum volume</label>
<div class="col-8">
<div class="row">
<div class="col">
<input id="maximum-volume" name="maximum-volume" type="range" min="20" max="99" step="1" class="custom-range form-control here d-none d-md-block" value="99">
<div class="row h-100">
<div class="col text-secondary d-none d-md-block">20</div>
<output name="maximum-volume" id="maximum-volume" class="col text-left text-md-center my-auto my-md-0">99</output>
<div class="col text-right text-secondary d-none d-md-block">99</div>
</div>
</div>
<div class="col-auto">
<button id="decrease-maximum-volume" aria-label="maximum volume decrease" type="button" class="btn btn-secondary stepper" aria-label="Decrease Maximum Volume">
<i class="fas fa-minus"></I>
</button>
<button id="increase-maximum-volume" aria-label="maximum volume increase" type="button" class="btn btn-secondary stepper" aria-label="Increase Maximum Volume">
<i class="fas fa-plus"></I>
</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label for="maximum-on-volume" class="col-3 col-form-label">Maximum On Volume</label>
<div class="col-8">
<div class="row">
<div class="col">
<input id="maximum-on-volume" name="maximum-on-volume" type="range" min="20" max="99" step="1" class="custom-range form-control here d-none d-md-block" value="50">
<div class="row h-100">
<div class="col text-secondary d-none d-md-block">20</div>
<output name="maximum-on-volume" id="maximum-on-volume" class="col text-left text-md-center my-auto my-md-0">50</output>
<div class="col text-right text-secondary d-none d-md-block">99</div>
</div>
</div>
<div class="col-auto">
<button id="decrease-maximum-on-volume" aria-label="maximum on volume decrease" type="button" class="btn btn-secondary stepper" aria-label="Decrease Maximum On Volume">
<i class="fas fa-minus"></I>
</button>
<button id="increase-maximum-on-volume" aria-label="maximum on volume increase" type="button" class="btn btn-secondary stepper" aria-label="Increase Maximum On Volume">
<i class="fas fa-plus"></I>
</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label for="display-on-time" class="col-3 col-form-label">Display on time</label>
<div class="col-8">
<select id="display-on-time" name="display-on-time" class="custom-select">
<option value="0">5 seconds</option>
<option value="1">10 seconds</option>
<option value="2">30 seconds</option>
<option value="3">1 minute</option>
<option value="4" selected>Always On</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="control-options" class="col-3 col-form-label">Control options</label>
<div class="col-8">
<select id="control-options" name="control-options" class="custom-select" disabled>
<option value="0">Off</option>
<option value="1">RS232</option>
<option value="2" selected>IP</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="power-on" class="col-3 col-form-label">Power on</label>
<div class="col-8">
<select id="power-on" name="power-on" class="custom-select">
<option value="0" selected>Last State</option>
<option value="1">Standby</option>
<option value="2">On</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="language" class="col-3 col-form-label">Language</label>
<div class="col-8">
<select id="language" name="language" class="custom-select">
<option value="0" selected>English</option>
<option value="1">Francais</option>
<option value="2">Deutsch</option>
<option value="3">Español</option>
<option value="4">Nederlands</option>
<option value="5">Pусский</option>
<option value="6">中文</option>
</select>
</div>
</div>
</form>
The .js content is:
$(document).ready(function () {
const maxVolId = "#maximum-volume";
const maxOnVolId = "#maximum-on-volume";
startup();
function startup() {
restorePreviousValues();
$(maxVolId).on("input", maximumVolumeChanged);
$(maxOnVolId).on("input", maximumOnVolumeChanged);
window.socketMessageReceived = function(msg) {
if (msg[2] == 0x1D) {
window.webSocket.send(0x29, [0xF0]);
} else if (msg[2] == 0x29) {
updateValuesUsing(parseGeneralSetupBuffer(msg));
} else if (msg[2] === 0x43) {
updateAudioFormat(msg[5], msg[6]);
} else if (msg[2] === 0x44) {
updateSampleRate(msg[5]);
}
};
window.webSocket.send(0x29, [0xF0]);
}
function updateAudioFormat(stream, channels) {
const model = updateModel("incoming-format", Utils.audioFormat(stream, channels));
}
function updateSampleRate(rate) {
const model = updateModel("incoming-sample-rate", Utils.parseSampleRate(rate));
updateValuesUsing(model);
}
function parseGeneralSetupBuffer(buffer) {
if (buffer.length != 38) {
throw "Invalid buffer length: " + buffer.length;
}
if (!validateCommandCode(buffer, 0x29)) {
throw "Invalid command code.";
}
var data = buffer.slice(5, buffer.length - 1);
return {
"source-input": Utils.asciiFromBuffer(data, { min: 0, max: 10 }),
"incoming-format": Utils.audioFormat(data[10], data[11]),
"incoming-sample-rate": Utils.parseSampleRate(data[12]),
"incoming-bitrate": Utils.parseBitrate(data[13]),
"dialnorm": Utils.parseDialNorm(data[14]),
"incoming-video-resolution": Utils.parseIncomingVideoResolution(data.slice(17,21)),
"audio-compression": data[23],
"balance": Utils.parseSignedValue(data[24]),
"dts-dialogue-control": data[25],
"maximum-volume": data[26],
"maximum-on-volume": data[27],
"display-on-time": data[28],
"control-options": data[29],
"power-on": data[30],
"language": data[31],
};
}
window.encodeModel = function(model) {
var data = new Array(32).fill(0);
data[23] = model["audio-compression"];
data[24] = Utils.toSignedValue(model["balance"]);
data[25] = model["dts-dialogue-control"];
data[26] = model["maximum-volume"];
data[27] = model["maximum-on-volume"];
data[28] = model["display-on-time"];
data[29] = model["control-options"];
data[30] = model["power-on"];
data[31] = model["language"];
return { code: 0x29, data: data };
};
function maximumVolumeChanged() {
var maxVol = $(maxVolId).val();
var maxOnVol = $(maxOnVolId).val();
if (maxVol < maxOnVol) {
$(maxOnVolId).val(maxVol);
}
}
function maximumOnVolumeChanged() {
var maxVol = $(maxVolId).val();
var maxOnVol = $(maxOnVolId).val();
if (maxOnVol > maxVol) {
$(maxOnVolId).val(maxVol);
}
}
window.shouldRespondToStepper = function(key, modifier) {
if (key === "maximum-on-volume" && modifier === "increase") {
return $(maxOnVolId).val() < $(maxVolId).val();
}
return true;
};
});