I found the following js file miner.b0d88d.js in the www/js folder. It handles the request to set_miner_conf.cgi, only showing the relavent snippet:
"use strict";
t.r(n);
var r = t(0),
o = (t(5), t(3), r.a);
o.loadProperties(), new Vue({
el: "#MinerSet",
data: () => ({
showLoading: !1,
minerForm: {
"bitmain-fan-ctrl": !1,
"bitmain-fan-pwm": "100",
"miner-mode": 0,
"freq-level": 100,
pools: [{
url: "",
user: "",
pass: ""
}, {
url: "",
user: "",
pass: ""
}, {
url: "",
user: "",
pass: ""
}]
},
modeList: [{
text: "",
id: 0
}, {
text: "",
id: 1
}]
}),
created() {
this.initData();
let e = window.ee;
e && (e.removeEvent("lang-changed"), e.addListener("lang-changed", this.updateModeList))
},
mounted() {
this.doMinerType()
},
computed: {
trShow() {
return 2 === this.minerForm["miner-mode"]
}
},
methods: {
doMinerType() {
$.ajax({
url: "/cgi-bin/get_system_info.cgi",
dataType: "json",
type: "GET",
timeout: 3e3,
async: !0,
processData: !1,
contentType: !1,
success: function(e) {
-1 != e.minertype.indexOf("Hydro") && (document.querySelector(".miner-machine-form table.table-form tbody tr:first-of-type").style.display = "none")
}
})
},
initData() {
var e = this;
this.updateModeList(), $.ajax({
url: "/cgi-bin/get_miner_conf.cgi",
dataType: "json",
type: "GET",
async: !1,
processData: !1,
contentType: !1,
success: function(n) {
if (n) {
for (i = 0; i < 3; i++) e.minerForm.pools[i].url = n.pools[i].url, e.minerForm.pools[i].user = n.pools[i].user, e.minerForm.pools[i].pass = n.pools[i].pass;
e.minerForm["bitmain-fan-ctrl"] = n["bitmain-fan-ctrl"], e.minerForm["bitmain-fan-pwm"] = n["bitmain-fan-pwm"], e.minerForm["miner-mode"] = n["bitmain-work-mode"], e.minerForm["freq-level"] = n["bitmain-freq-level"]
}
},
error: function() {
o.showWarn("error", "commonCode")
}
})
},
updateModeList() {
this.modeList[0].text = $.i18[Suspicious link removed]op("modeNormal"), this.modeList[1].text = $.i18[Suspicious link removed]op("modeSleep")
},
modeSelectChange(e) {
this.minerForm["miner-mode"] = e
},
checkFun(e) {
this.$set(this.minerForm, e, !this.minerForm[e])
},
saveMineSet() {
var e = JSON.stringify(this.minerForm),
n = this;
n.showLoading = !0, $.ajax({
url: "/cgi-bin/set_miner_conf.cgi",
dataType: "json",
type: "POST",
async: !0,
data: e,
processData: !1,
contentType: !1,
success: function(e) {
n.showLoading = !1;
var t = e;
"success" === t.stats ? o.showWarn("success",[Suspicious link removed]de) : o.showWarn("error",[Suspicious link removed]de), r.a.loadInner("miner")
},
error: function(e) {
n.showLoading = !1, o.showWarn("error", "commonCode"), r.a.loadInner("miner")
}
where the function saveMineSet(), does just post a JSON formatted string to set_miner_conf.cgi. I ended up using something like:
from requests.auth import HTTPDigestAuth
import json
confData = {}
confData['pools']= []
confData['pools'].append({"url": configInfo['url1'], "user": configInfo['user1'], "pass": configInfo['pass1']})
confData['pools'].append({"url": configInfo['url2'], "user": configInfo['user2'], "pass": configInfo['pass2']})
confData['pools'].append({"url": configInfo['url3'], "user": configInfo['user3'], "pass": configInfo['pass3']})
confPayload = json.dumps(confData)
setConfAddr = '/cgi-bin/set_miner_conf.cgi'
try:
r = requests.post('http://' + self.ip + setConfAddr, auth=HTTPDigestAuth(self.webUserName, self.webPassword), data=confPayload)
except:
self.error("post ant miner configuration failed.")
in python. The js file should give you insight on how to change some of the other configuration variables if needed. Setting network configuration is similar, and how to format the JSON that is posted to set_network_conf.cgi can be seen in the ip.1cc6a.js file (also in www/js/), again only showing relevant snippet:
69: function(n, e, t) {
"use strict";
t.r(e);
var r = t(0),
o = (t(5), t(3), r.a);
o.loadProperties(), new Vue({
el: "#ipSet",
data: () => ({
showLoading: !1,
ipForm: {
ipHost: "",
ipPro: 1,
ipAddress: "",
ipSub: "",
ipGateway: "",
ipDns: ""
},
ipInfo: {
ip: "",
mac: "",
mask: ""
},
sltList: [{
text: "DHCP",
id: 1
}, {
text: "Static",
id: 2
}]
}),
created() {
this.initData()
},
computed: {
trShow() {
return 2 === this.ipForm.ipPro
}
},
mounted() {},
methods: {
initData() {
var n = this;
$.ajax({
url: "/cgi-bin/get_network_info.cgi",
dataType: "json",
type: "GET",
async: !1,
processData: !1,
contentType: !1,
success: function(e) {
e && (n.ipForm.ipHost = e.conf_hostname, n.ipForm.ipPro = "DHCP" == e.conf_nettype ? 1 : 2, n.ipForm.ipAddress = e.conf_ipaddress, n.ipForm.ipSub = e.conf_netmask, n.ipForm.ipGateway = e.conf_gateway, n.ipForm.ipDns = e.conf_dnsservers, n.ipInfo.ip = e.ipaddress, n.ipInfo.mac = e.macaddr, n.ipInfo.mask = e.netmask)
},
error: function() {
r.a.showWarn("error")
}
})
},
proSelectChange(n) {
this.ipForm.ipPro = n
},
saveIpSet() {
var n = JSON.stringify(this.ipForm),
e = this;
e.showLoading = !0, $.ajax({
url: "/cgi-bin/set_network_conf.cgi",
dataType: "json",
type: "POST",
async: !0,
data: n,
processData: !1,
contentType: !1,
success: function(n) {
e.showLoading = !1;
var t = n;
"success" === t.stats ? o.showWarn("success",[Suspicious link removed]de) : o.showWarn("error",[Suspicious link removed]de), r.a.loadInner("ip")
},
error: function(n) {
e.showLoading = !1, o.showWarn("error", "commonCode"), r.a.loadInner("ip")
}
I hope this helps anyone in the future from having to unpack the firmware and figure out how the web interface communicates with the cgi-bin files.