mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-12 00:02:53 +00:00
Added option to select firmware channel
This commit is contained in:
parent
c648546b61
commit
01c7326a46
@ -50,6 +50,11 @@
|
||||
#define LED_BEHAVIOUR_ERROR_ONLY 3
|
||||
#define LED_BEHAVIOUR_OFF 9
|
||||
|
||||
#define FIRMWARE_CHANNEL_STABLE 0
|
||||
#define FIRMWARE_CHANNEL_EARLY 1
|
||||
#define FIRMWARE_CHANNEL_RC 2
|
||||
#define FIRMWARE_CHANNEL_SNAPSHOT 3
|
||||
|
||||
struct ResetDataContainer {
|
||||
uint8_t cause;
|
||||
uint8_t last_cause;
|
||||
@ -63,6 +68,7 @@ struct SystemConfig {
|
||||
uint8_t dataCollectionConsent; // 0 = unknown, 1 = accepted, 2 = declined
|
||||
char country[3];
|
||||
uint8_t energyspeedometer;
|
||||
uint8_t firmwareChannel;
|
||||
}; // 8
|
||||
|
||||
struct NetworkConfig {
|
||||
|
||||
@ -15,6 +15,11 @@ bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
||||
uint8_t configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||
EEPROM.get(CONFIG_SYSTEM_START, config);
|
||||
EEPROM.end();
|
||||
|
||||
if(config.firmwareChannel > 3) {
|
||||
config.firmwareChannel = 0;
|
||||
}
|
||||
|
||||
if(configVersion == EEPROM_CHECK_SUM) {
|
||||
return true;
|
||||
} else {
|
||||
@ -27,6 +32,7 @@ bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
||||
}
|
||||
config.userConfigured = false;
|
||||
config.dataCollectionConsent = 0;
|
||||
config.firmwareChannel = 0;
|
||||
config.energyspeedometer = 0;
|
||||
memset(config.country, 0, 3);
|
||||
return false;
|
||||
@ -42,6 +48,9 @@ bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
||||
sysChanged |= config.dataCollectionConsent != existing.dataCollectionConsent;
|
||||
sysChanged |= strcmp(config.country, existing.country) != 0;
|
||||
sysChanged |= config.energyspeedometer != existing.energyspeedometer;
|
||||
sysChanged |= config.firmwareChannel != existing.firmwareChannel;
|
||||
} else {
|
||||
sysChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
stripNonAscii((uint8_t*) config.country, 2);
|
||||
@ -979,6 +988,7 @@ void AmsConfiguration::clear() {
|
||||
EEPROM.get(CONFIG_SYSTEM_START, sys);
|
||||
sys.userConfigured = false;
|
||||
sys.dataCollectionConsent = 0;
|
||||
sys.firmwareChannel = 0;
|
||||
sys.energyspeedometer = 0;
|
||||
memset(sys.country, 0, 3);
|
||||
EEPROM.put(CONFIG_SYSTEM_START, sys);
|
||||
|
||||
@ -60,6 +60,13 @@ public:
|
||||
bool isUpgradeInformationChanged();
|
||||
void ackUpgradeInformationChanged();
|
||||
|
||||
void setFirmwareChannel(uint8_t channel) {
|
||||
if(firmwareChannel != channel) {
|
||||
firmwareChannel = channel;
|
||||
lastVersionCheck = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool startFirmwareUpload(uint32_t size, const char* version);
|
||||
bool addFirmwareUploadChunk(uint8_t* buf, size_t length);
|
||||
bool completeFirmwareUpload(uint32_t size);
|
||||
@ -95,10 +102,11 @@ private:
|
||||
String md5;
|
||||
|
||||
uint32_t lastVersionCheck = 0;
|
||||
uint8_t firmwareVariant;
|
||||
uint8_t firmwareChannel;
|
||||
bool autoUpgrade;
|
||||
char nextVersion[17];
|
||||
|
||||
void getChannelName(char * buffer);
|
||||
|
||||
bool fetchNextVersion();
|
||||
bool fetchVersionDetails();
|
||||
|
||||
@ -22,7 +22,7 @@ this->debugger = debugger;
|
||||
this->hw = hw;
|
||||
this->meterState = meterState;
|
||||
memset(nextVersion, 0, sizeof(nextVersion));
|
||||
firmwareVariant = 0;
|
||||
firmwareChannel = 0;
|
||||
autoUpgrade = false;
|
||||
}
|
||||
|
||||
@ -208,15 +208,33 @@ void AmsFirmwareUpdater::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
void AmsFirmwareUpdater::getChannelName(char * buffer) {
|
||||
switch(firmwareChannel) {
|
||||
case FIRMWARE_CHANNEL_EARLY:
|
||||
strcpy(buffer, PSTR("early"));
|
||||
break;
|
||||
case FIRMWARE_CHANNEL_RC:
|
||||
strcpy(buffer, PSTR("rc"));
|
||||
break;
|
||||
case FIRMWARE_CHANNEL_SNAPSHOT:
|
||||
strcpy(buffer, PSTR("snapshot"));
|
||||
break;
|
||||
default:
|
||||
strcpy(buffer, PSTR("stable"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool AmsFirmwareUpdater::fetchNextVersion() {
|
||||
HTTPClient http;
|
||||
const char * headerkeys[] = { "x-version" };
|
||||
http.collectHeaders(headerkeys, 1);
|
||||
|
||||
char firmwareVariant[10] = "stable";
|
||||
char channel[10] = "";
|
||||
getChannelName(channel);
|
||||
|
||||
char url[128];
|
||||
snprintf_P(url, 128, PSTR("http://hub.amsleser.no/hub/firmware/%s/%s/next"), chipType, firmwareVariant);
|
||||
snprintf_P(url, 128, PSTR("http://hub.amsleser.no/hub/firmware/%s/%s/next"), chipType, channel);
|
||||
#if defined(ESP8266)
|
||||
WiFiClient client;
|
||||
client.setTimeout(5000);
|
||||
@ -263,10 +281,11 @@ bool AmsFirmwareUpdater::fetchVersionDetails() {
|
||||
const char * headerkeys[] = { "x-size" };
|
||||
http.collectHeaders(headerkeys, 1);
|
||||
|
||||
char firmwareVariant[10] = "stable";
|
||||
char channel[10] = "";
|
||||
getChannelName(channel);
|
||||
|
||||
char url[128];
|
||||
snprintf_P(url, 128, PSTR("http://hub.amsleser.no/hub/firmware/%s/%s/%s/details"), chipType, firmwareVariant, updateStatus.toVersion);
|
||||
snprintf_P(url, 128, PSTR("http://hub.amsleser.no/hub/firmware/%s/%s/%s/details"), chipType, channel, updateStatus.toVersion);
|
||||
#if defined(ESP8266)
|
||||
WiFiClient client;
|
||||
client.setTimeout(5000);
|
||||
@ -319,10 +338,11 @@ bool AmsFirmwareUpdater::fetchFirmwareChunk(HTTPClient& http) {
|
||||
char range[24];
|
||||
snprintf_P(range, 24, PSTR("bytes=%lu-%lu"), start, end);
|
||||
|
||||
char firmwareVariant[10] = "stable";
|
||||
char channel[10] = "";
|
||||
getChannelName(channel);
|
||||
|
||||
char url[128];
|
||||
snprintf_P(url, 128, PSTR("http://hub.amsleser.no/hub/firmware/%s/%s/%s/chunk"), chipType, firmwareVariant, updateStatus.toVersion);
|
||||
snprintf_P(url, 128, PSTR("http://hub.amsleser.no/hub/firmware/%s/%s/%s/chunk"), chipType, channel, updateStatus.toVersion);
|
||||
#if defined(ESP8266)
|
||||
WiFiClient client;
|
||||
client.setTimeout(5000);
|
||||
|
||||
13
lib/SvelteUi/app/dist/index.js
vendored
13
lib/SvelteUi/app/dist/index.js
vendored
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { metertype, boardtype, isBusPowered, getBaseChip } from './Helpers.js';
|
||||
import { metertype, boardtype, isBusPowered, getBaseChip, wiki } from './Helpers.js';
|
||||
import { getSysinfo, sysinfoStore } from './DataStores.js';
|
||||
import { upgrade, upgradeWarningText } from './UpgradeHelper';
|
||||
import { translationsStore } from './TranslationService.js';
|
||||
@ -108,6 +108,15 @@
|
||||
});
|
||||
};
|
||||
|
||||
function changeFirmwareChannel() {
|
||||
const formData = new FormData();
|
||||
formData.append('channel', sysinfo.upgrade.c);
|
||||
fetch('fwchannel', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
};
|
||||
|
||||
$: {
|
||||
if(configFiles.length == 1) {
|
||||
let file = configFiles[0];
|
||||
@ -209,25 +218,37 @@
|
||||
{/if}
|
||||
<div class="cnt">
|
||||
<strong class="text-sm">{translations.status?.firmware?.title ?? "Firmware"}</strong>
|
||||
<a href="{wiki('Firmware-Channels')}" target="_blank" class="float-right">ⓘ</a>
|
||||
{#if sysinfo.fwconsent === 1}
|
||||
<div class="my-2">
|
||||
Channel:
|
||||
<select class="in-s w-full" bind:value={sysinfo.upgrade.c} on:change={changeFirmwareChannel}>
|
||||
<option value={0}>Stable</option>
|
||||
<option value={1}>Early</option>
|
||||
<option value={2}>Release Candidate</option>
|
||||
<option value={3} disabled>Snapshot</option>
|
||||
</select>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="my-2">
|
||||
{translations.status?.firmware?.installed ?? "Installed"}: {sysinfo.version}
|
||||
</div>
|
||||
{#if sysinfo.upgrade.t && sysinfo.upgrade.t != sysinfo.version && sysinfo.upgrade.e != 0 && sysinfo.upgrade.e != 123}
|
||||
<div class="my-2">
|
||||
<div class="bd-yellow">
|
||||
{(translations.status?.firmware?.failed ?? "Upgrade from {0} to {1} failed").replace('{0}', sysinfo.upgrade.f).replace('{1}', sysinfo.upgrade.t)}
|
||||
{(translations.errors?.upgrade?.[sysinfo.upgrade.e] ?? sysinfo.upgrade.e)}
|
||||
<div class="my-2">
|
||||
<div class="bd-yellow">
|
||||
{(translations.status?.firmware?.failed ?? "Upgrade from {0} to {1} failed").replace('{0}', sysinfo.upgrade.f).replace('{1}', sysinfo.upgrade.t)}
|
||||
{(translations.errors?.upgrade?.[sysinfo.upgrade.e] ?? sysinfo.upgrade.e)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if sysinfo.upgrade.n}
|
||||
<div class="my-2 flex">
|
||||
{translations.status?.firmware?.latest ?? "Latest"}:
|
||||
<a href={"https://github.com/UtilitechAS/amsreader-firmware/releases/tag/" + sysinfo.upgrade.n} class="ml-2 text-blue-600 hover:text-blue-800" target='_blank' rel="noreferrer">{sysinfo.upgrade.n}</a>
|
||||
{#if (sysinfo.security == 0 || data.a) && sysinfo.fwconsent === 1 && sysinfo.upgrade.n && sysinfo.upgrade.n != sysinfo.version}
|
||||
<div class="flex-none ml-2 text-green-500" title={translations.status?.firmware?.install ?? "Install"}>
|
||||
<button on:click={askUpgrade}>⇓</button>
|
||||
</div>
|
||||
<div class="flex-none ml-2 text-green-500" title={translations.status?.firmware?.install ?? "Install"}>
|
||||
<button on:click={askUpgrade}>⇓</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if sysinfo.fwconsent === 2}
|
||||
@ -237,22 +258,22 @@
|
||||
{/if}
|
||||
{/if}
|
||||
{#if (sysinfo.security == 0 || data.a) && isBusPowered(sysinfo.board) }
|
||||
<div class="bd-red">
|
||||
{upgradeWarningText(boardtype(sysinfo.chip, sysinfo.board))}
|
||||
</div>
|
||||
<div class="bd-red">
|
||||
{upgradeWarningText(boardtype(sysinfo.chip, sysinfo.board))}
|
||||
</div>
|
||||
{/if}
|
||||
{#if sysinfo.security == 0 || data.a}
|
||||
<div class="my-2 flex">
|
||||
<form action="firmware" enctype="multipart/form-data" method="post" on:submit={() => firmwareUploading=true} autocomplete="off">
|
||||
<input style="display:none" name="file" type="file" accept=".bin" bind:this={firmwareFileInput} bind:files={firmwareFiles}>
|
||||
{#if firmwareFiles.length == 0}
|
||||
<button type="button" on:click={()=>{firmwareFileInput.click();}} class="btn-pri-sm float-right">{translations.status?.firmware?.btn_select_file ?? "Select file"}</button>
|
||||
{:else}
|
||||
{firmwareFiles[0].name}
|
||||
<button type="submit" class="btn-pri-sm float-right ml-2">{translations.btn?.upload ?? "Upload"}</button>
|
||||
{/if}
|
||||
</form>
|
||||
</div>
|
||||
<div class="my-2 flex">
|
||||
<form action="firmware" enctype="multipart/form-data" method="post" on:submit={() => firmwareUploading=true} autocomplete="off">
|
||||
<input style="display:none" name="file" type="file" accept=".bin" bind:this={firmwareFileInput} bind:files={firmwareFiles}>
|
||||
{#if firmwareFiles.length == 0}
|
||||
<button type="button" on:click={()=>{firmwareFileInput.click();}} class="btn-pri-sm float-right">{translations.status?.firmware?.btn_select_file ?? "Select file"}</button>
|
||||
{:else}
|
||||
{firmwareFiles[0].name}
|
||||
<button type="submit" class="btn-pri-sm float-right ml-2">{translations.btn?.upload ?? "Upload"}</button>
|
||||
{/if}
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if sysinfo.security == 0 || data.a}
|
||||
|
||||
@ -146,6 +146,7 @@ private:
|
||||
void firmwarePost();
|
||||
void firmwareUpload();
|
||||
void isAliveCheck();
|
||||
void fwchannel();
|
||||
|
||||
void mqttCaUpload();
|
||||
void mqttCaDelete();
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
"boot_reason": %d,
|
||||
"ex_cause": %d,
|
||||
"upgrade": {
|
||||
"c": %d,
|
||||
"e": %d,
|
||||
"f": "%s",
|
||||
"t": "%s",
|
||||
|
||||
@ -145,6 +145,7 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, AmsDa
|
||||
server.on(context + F("/firmware"), HTTP_GET, std::bind(&AmsWebServer::firmwareHtml, this));
|
||||
server.on(context + F("/firmware"), HTTP_POST, std::bind(&AmsWebServer::firmwarePost, this), std::bind(&AmsWebServer::firmwareUpload, this));
|
||||
server.on(context + F("/is-alive"), HTTP_GET, std::bind(&AmsWebServer::isAliveCheck, this));
|
||||
server.on(context + F("/fwchannel"), HTTP_POST, std::bind(&AmsWebServer::fwchannel, this));
|
||||
|
||||
server.on(context + F("/reset"), HTTP_POST, std::bind(&AmsWebServer::factoryResetPost, this));
|
||||
|
||||
@ -479,6 +480,7 @@ void AmsWebServer::sysinfoJson() {
|
||||
ESP.getResetInfoPtr()->reason,
|
||||
ESP.getResetInfoPtr()->exccause,
|
||||
#endif
|
||||
sys.firmwareChannel,
|
||||
upinfo.errorCode,
|
||||
upinfo.fromVersion,
|
||||
upinfo.toVersion,
|
||||
@ -1341,6 +1343,7 @@ void AmsWebServer::handleSave() {
|
||||
|
||||
sys.userConfigured = success;
|
||||
sys.dataCollectionConsent = 0;
|
||||
sys.firmwareChannel = 0;
|
||||
config->setSystemConfig(sys);
|
||||
|
||||
performRestart = true;
|
||||
@ -2022,6 +2025,17 @@ void AmsWebServer::isAliveCheck() {
|
||||
server.send(200);
|
||||
}
|
||||
|
||||
void AmsWebServer::fwchannel() {
|
||||
if(!checkSecurity(1))
|
||||
return;
|
||||
|
||||
SystemConfig sys;
|
||||
config->getSystemConfig(sys);
|
||||
sys.firmwareChannel = server.arg(F("channel")).toInt();
|
||||
config->setSystemConfig(sys);
|
||||
server.send(200);
|
||||
}
|
||||
|
||||
void AmsWebServer::factoryResetPost() {
|
||||
if(!checkSecurity(1))
|
||||
return;
|
||||
|
||||
@ -1120,6 +1120,7 @@ void handleSystem(unsigned long now) {
|
||||
if(config.isSystemConfigChanged()) {
|
||||
config.getSystemConfig(sysConfig);
|
||||
config.ackSystemConfigChanged();
|
||||
updater.setFirmwareChannel(sysConfig.firmwareChannel);
|
||||
}
|
||||
|
||||
unsigned long start, end;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user