Author

Topic: Updating pool settings via CGI on S19Pro (Read 112 times)

newbie
Activity: 14
Merit: 16
August 06, 2021, 03:35:22 PM
#5
Hi Everyone, cant post the full js code snippets as they are too long and I get empty body error. I got things to work like OP suggested.
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:

Code:
    68: function(e, n, t) {
        "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:

Code:
                import requests
                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:

Code:
!
    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.
newbie
Activity: 14
Merit: 16
August 06, 2021, 11:21:13 AM
#4
I guess the the new cgi_get_POST_vars function accepts POST message in a different way than before, I am no bash expert and cant exactly decipher what is accepted by the cgi script. The set_network_conf file from the unpacked firmware is:

Code:
#!/bin/sh

function cgi_get_POST_vars()
{
    # check content type
    # FIXME: not sure if we could handle uploads with this..
    [ "${CONTENT_TYPE}" != "application/x-www-form-urlencoded" ] && \
    echo "Warning: you should probably use MIME type "\
         "application/x-www-form-urlencoded!" 1>&2
    # save POST variables (only first time this is called)
    [ -z "$QUERY_STRING_POST" \
      -a "$REQUEST_METHOD" = "POST" -a ! -z "$CONTENT_LENGTH" ] && \
    read -n $CONTENT_LENGTH QUERY_STRING_POST
    return
}

function update_network_conf_file()
{
    config_file="/config/network.conf"
    if [ "${ant_conf_nettype}" == "1" ]; then
        echo "dhcp=true"                                >  $config_file
        echo "hostname=${ant_conf_hostname}"            >> $config_file
    else
        echo "hostname=${ant_conf_hostname}"            >  $config_file
        echo "ipaddress=${ant_conf_ipaddress}"          >> $config_file
        echo "netmask=${ant_conf_netmask}"              >> $config_file
        echo "gateway=${ant_conf_gateway}"              >> $config_file
        echo "dnsservers=${ant_conf_dnsservers}"        >> $config_file
    fi
}

function check_param()
{
    if ! echo "$ant_conf_hostname" | egrep -q "$regex_hostname"; then
        return 1
    fi

    if [ "${ant_conf_nettype}" == "2" ]; then
        if ! echo "${ant_conf_ipaddress}" | egrep -q "$regex_ip"; then
            return 2
        fi
        if ! echo "${ant_conf_netmask}" | egrep -q "$regex_ip" ; then
            return 3
        fi
        if ! echo "${ant_conf_gateway}" | egrep -q "$regex_ip"; then
            return 4
        fi
        if ! echo "${ant_conf_dnsservers}" | egrep -q "$regex_ip"; then
            return 5
        fi
    fi
    return 0
}

ant_conf_nettype=
ant_conf_hostname=
ant_conf_ipaddress=
ant_conf_netmask=
ant_conf_gateway=
ant_conf_dnsservers=
stats="error"
err_flag=0
msg=

regex_ip="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
regex_hostname="^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$"

cgi_get_POST_vars
#echo $QUERY_STRING_POST > /tmp/a
#QUERY_STRING_POST=`cat /tmp/a`
ant_conf_nettype=`echo $QUERY_STRING_POST | jq -r ".ipPro"`
ant_conf_hostname=`echo $QUERY_STRING_POST | jq -r ".ipHost"`
if [ "${ant_conf_nettype}" == "2" ];then
    ant_conf_ipaddress=`echo $QUERY_STRING_POST | jq -r ".ipAddress"`
    ant_conf_netmask=`echo $QUERY_STRING_POST | jq -r ".ipSub"`
    ant_conf_gateway=`echo $QUERY_STRING_POST | jq -r ".ipGateway"`
    ant_conf_dnsservers=`echo $QUERY_STRING_POST | jq -r ".ipDns"`
fi

check_param
err_flag=$?

if [ $err_flag -eq 0 ]; then
    msg="OK!"
    stats="success"
fi
if [ $err_flag -eq 1 ]; then
    msg="Hostname invalid!"
fi
if [ $err_flag -eq 2 ]; then
    msg="IP invalid!"
fi
if [ $err_flag -eq 3 ]; then
    msg="Netmask invalid!"
fi
if [ $err_flag -eq 4 ]; then
    msg="Gateway invalid!"
fi
if [ $err_flag -eq 5 ]; then
    msg="DNS invalid!"
fi

echo "{\"stats\":\"$stats\",\"code\":\"N00$err_flag\",\"msg\":\"$msg\"}"

if [ $err_flag -eq 0 ];then
    update_network_conf_file
    sync
    sleep 1s
    sudo /etc/init.d/S38network restart > /dev/null 2>&1 &
fi


for completeness.

Is the get POST variables function specifying to the exact JSON styled message as OP suggests?
newbie
Activity: 14
Merit: 16
August 06, 2021, 10:59:22 AM
#3
I have previously always sent a payload using urllib.parse.urlencode  through request for S9 generation miners, I am getting an illegal request  error using the same where the set_miner_conf.cgi file I unpacked from a 2021 April firmware is :

Code:
#!/bin/sh

function cgi_get_POST_vars()
{
    [ "${CONTENT_TYPE}" != "application/x-www-form-urlencoded" ] && \
    echo "Warning: you should probably use MIME type "\
         "application/x-www-form-urlencoded!" 1>&2
    [ -z "$QUERY_STRING_POST" \
      -a "$REQUEST_METHOD" = "POST" -a ! -z "$CONTENT_LENGTH" ] && \
    read -n $CONTENT_LENGTH QUERY_STRING_POST
    return
}

function update_config_file()
{
    config_file="/config/cgminer.conf"
    echo "{"                                                            > $config_file
    echo "\"pools\" : ["                                                >> $config_file
    echo "{"                                                            >> $config_file
    echo "\"url\" : \"$ant_pool1url\","                                 >> $config_file
    echo "\"user\" : \"$ant_pool1user\","                               >> $config_file
    echo "\"pass\" : \"$ant_pool1pw\""                                  >> $config_file
    echo "},"                                                           >> $config_file
    echo "{"                                                            >> $config_file
    echo "\"url\" : \"$ant_pool2url\","                                 >> $config_file
    echo "\"user\" : \"$ant_pool2user\","                               >> $config_file
    echo "\"pass\" : \"$ant_pool2pw\""                                  >> $config_file
    echo "},"                                                           >> $config_file
    echo "{"                                                            >> $config_file
    echo "\"url\" : \"$ant_pool3url\","                                 >> $config_file
    echo "\"user\" : \"$ant_pool3user\","                               >> $config_file
    echo "\"pass\" : \"$ant_pool3pw\""                                  >> $config_file
    echo "}"                                                            >> $config_file
    echo "]"                                                            >> $config_file
    echo ","                                                            >> $config_file
    echo "\"api-listen\" : true,"                                       >> $config_file
    echo "\"api-network\" : true,"                                      >> $config_file
    echo "\"api-groups\" : \"A:stats:pools:devs:summary:version\","     >> $config_file
    echo "\"api-allow\" : \"A:0/0,W:*\","                               >> $config_file
    echo "\"bitmain-fan-ctrl\" : $ant_fan_customize_value,"             >> $config_file
    echo "\"bitmain-fan-pwm\" : \"$ant_fan_customize_switch\","         >> $config_file
    echo "\"bitmain-use-vil\" : true,"                                  >> $config_file
    echo "\"bitmain-freq\" : \"$ant_freq\","                            >> $config_file
    echo "\"bitmain-voltage\" : \"$ant_voltage\","                      >> $config_file
    echo "\"bitmain-ccdelay\" : \"$ant_ccdelay\","                      >> $config_file
    echo "\"bitmain-pwth\" : \"$ant_pwth\","                            >> $config_file
    echo "\"bitmain-work-mode\" : \"$ant_miner_mode\","                 >> $config_file
    echo "\"bitmain-freq-level\" : \"$ant_freq_level\""                 >> $config_file
    #echo "\"miner-mode\" : \"$ant_work_mode\","                        >> $config_file
    #echo "\"freq-level\" : \"$ant_freq_level\""                        >> $config_file
    echo "}"                                                            >> $config_file
}

function parse_configs()
{
    echo $1 | jq -r $2
}

function old_configs()
{
    cat /config/cgminer.conf | jq -r $1
}
reload=false
cgi_get_POST_vars

#echo $QUERY_STRING_POST > /tmp/aaa
#QUERY_STRING_POST=`cat /tmp/aaa`

echo $QUERY_STRING_POST | jq > /dev/null

if [[ $? -eq 0 ]]&&[[ ! "$QUERY_STRING_POST"x == ""x ]]; then
QUERY_STRING_POST=`echo $QUERY_STRING_POST | jq -c`
    ret=`parse_configs $QUERY_STRING_POST ".pools[0].url"`
    if [ "$ret"x == "null"x ];then
        ant_pool1url=`old_configs ".pools[0].url"`
    else
        ant_pool1url=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[0].user"`
    if [ "$ret"x == "null"x ];then
        ant_pool1user=`old_configs ".pools[0].user"`
    else
        ant_pool1user=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[0].pass"`
    if [ "$ret"x == "null"x ];then
        ant_pool1pw=`old_configs ".pools[0].pass"`
    else
        ant_pool1pw=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[1].url"`
    if [ "$ret"x == "null"x ];then
        ant_pool2url=`old_configs ".pools[1].url"`
    else
        ant_pool2url=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[1].user"`
    if [ "$ret"x == "null"x ];then
        ant_pool2user=`old_configs ".pools[1].user"`
    else
        ant_pool2user=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[1].pass"`
    if [ "$ret"x == "null"x ];then
        ant_pool2pw=`old_configs ".pools[1].pass"`
    else
        ant_pool2pw=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[2].url"`
    if [ "$ret"x == "null"x ];then
        ant_pool3url=`old_configs ".pools[2].url"`
    else
        ant_pool3url=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[2].user"`
    if [ "$ret"x == "null"x ];then
        ant_pool3user=`old_configs ".pools[2].user"`
    else
        ant_pool3user=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST ".pools[2].pass"`
    if [ "$ret"x == "null"x ];then
        ant_pool3pw=`old_configs ".pools[2].pass"`
    else
        ant_pool3pw=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST '."bitmain-fan-ctrl"'`
    if [ "$ret"x == "null"x ];then
        ant_fan_customize_value=`old_configs '."bitmain-fan-ctrl"'`
    else
        ant_fan_customize_value=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST '."bitmain-fan-pwm"'`
    if [ "$ret"x == "null"x ];then
        ant_fan_customize_switch=`old_configs '."bitmain-fan-pwm"'`
    else
        ant_fan_customize_switch=$ret
    fi
    ret=`parse_configs $QUERY_STRING_POST '."miner-mode"'`
    if [[ "$ret"x == "null"x ]]||([[ $ret -ne 0 ]]&&[[ $ret -ne 1 ]]);then
        ant_miner_mode=`old_configs '."bitmain-work-mode"'`
        reload=true
    else
        old_ant_miner_mode=`old_configs '."bitmain-work-mode"'`
        ant_miner_mode=$ret
        if [ $old_ant_miner_mode == $ret ];then
            reload=true
        fi
    fi
    ret=`parse_configs $QUERY_STRING_POST '."freq-level"'`
    if [ "$ret"x == "null"x ];then
        ant_freq_level=`old_configs '."bitmain-freq-level"'`
    else
        ant_freq_level=$ret
    fi
    ant_ccdelay=`old_configs '."bitmain-ccdelay"'`
    ant_pwth=`old_configs '."bitmain-pwth"'`
    ant_freq=`old_configs '."bitmain-freq"'`
    ant_voltage=`old_configs '."bitmain-voltage"'`
#   ret=`parse_configs $QUERY_STRING_POST '."bitmain-freq"'`
#   if [ "$ret"x == "null"x ];then
#       ant_freq=`old_configs '."bitmain-freq"'`
#   else
#       ant_freq=$ret
#   fi
#   ret=`parse_configs $QUERY_STRING_POST '."bitmain-voltage"'`
#   if [ "$ret"x == "null"x ];then
#       ant_voltage=`old_configs '."bitmain-voltage"'`
#   else
#       ant_voltage=$ret
#   fi
#   ret=`parse_configs $QUERY_STRING_POST '."bitmain-ccdelay"'`
#   if [ "$ret"x == "null"x ];then
#       ant_ccdelay=`old_configs '."bitmain-ccdelay"'`
#   else
#       ant_ccdelay=$ret
#   fi
#   ret=`parse_configs $QUERY_STRING_POST '."bitmain-pwth"'`
#   if [ "$ret"x == "null"x ];then
#       ant_pwth=`old_configs '."bitmain-pwth"'`
#   else
#       ant_pwth=$ret
#   fi

    update_config_file
    sync
    sleep 1s
   
    if [ $reload == true ];then
        cgminer-api {\"command\":\"reload\",\"new_api\":true} > /dev/null &
    else
        sudo /etc/init.d/S70cgminer restart > /dev/null &
    fi

    echo "{\"stats\":\"success\",\"code\":\"M000\",\"msg\":\"OK!\"}"
else
    echo "{\"stats\":\"error\",\"code\":\"M001\",\"msg\":\"Illegal request!\"}"
fi

Are you saying to just literally post what you provided in your own response to set_miner_conf.cgi instead? I also need to use set_network_conf to update hostname, so would like to replicate exactly what the web interface sends to  its own cgi files when manually submitting a manual input. Anyone had any luck with this?

I get the following response


         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 
  500 - Internal Server Error
 
 
 

500 - Internal Server Error


 


when sending what I always had to S9 (and equivalent), to the set_network_conf,cgi file as well.

Any more insite would be great!

Thanks!
newbie
Activity: 20
Merit: 0
SOLVED. I had to POST the following to set_miner_conf.cgi:

    data = {
        "pools": [
            {
                 "url": "antpool.com:3333",
                 "user": "antminer1,
                 "pass": ""
             },
             {
                 "url": "antpool.com:3333",
                 "user": "antminer1",
                 "pass": ""
             },
             {
                  "url": "antpool.com:3333",
                  "user": "antminer1",
                  "pass": ""
              }
           ]
      }
newbie
Activity: 20
Merit: 0
Hi all,

Just wondering if anyone has been able to update the pool settings on an S19Pro via CGI. I wrote a script that used to work on S9's but it doesn't work on S19Pro units. It also worked on the S17's. Any insights would be appreciated!
Jump to: