Bitcoin Forum
May 02, 2024, 02:38:37 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Updating pool settings via CGI on S19Pro  (Read 115 times)
Morescratch (OP)
Newbie
*
Offline Offline

Activity: 20
Merit: 0


View Profile
May 24, 2021, 05:25:49 PM
 #1

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!
1714660717
Hero Member
*
Offline Offline

Posts: 1714660717

View Profile Personal Message (Offline)

Ignore
1714660717
Reply with quote  #2

1714660717
Report to moderator
1714660717
Hero Member
*
Offline Offline

Posts: 1714660717

View Profile Personal Message (Offline)

Ignore
1714660717
Reply with quote  #2

1714660717
Report to moderator
1714660717
Hero Member
*
Offline Offline

Posts: 1714660717

View Profile Personal Message (Offline)

Ignore
1714660717
Reply with quote  #2

1714660717
Report to moderator
"I'm sure that in 20 years there will either be very large transaction volume or no volume." -- Satoshi
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
Morescratch (OP)
Newbie
*
Offline Offline

Activity: 20
Merit: 0


View Profile
May 24, 2021, 06:39:45 PM
 #2

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": ""
              }
           ]
      }
s3binator
Newbie
*
Offline Offline

Activity: 14
Merit: 16


View Profile
August 06, 2021, 02:59:22 PM
 #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

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>500 - Internal Server Error</title>
 </head>
 <body>
  <h1>500 - Internal Server Error</h1>
 </body>
</html>

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!
s3binator
Newbie
*
Offline Offline

Activity: 14
Merit: 16


View Profile
August 06, 2021, 03:21:13 PM
 #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?
s3binator
Newbie
*
Offline Offline

Activity: 14
Merit: 16


View Profile
August 06, 2021, 07: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.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!