github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/plugins/cgminer/bitmine/bitmine.go (about)

     1  // This file is part of the Smart Home
     2  // Program complex distribution https://github.com/e154/smart-home
     3  // Copyright (C) 2016-2023, Filippov Alex
     4  //
     5  // This library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU Lesser General Public
     7  // License as published by the Free Software Foundation; either
     8  // version 3 of the License, or (at your option) any later version.
     9  //
    10  // This library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  // Library General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public
    16  // License along with this library.  If not, see
    17  // <https://www.gnu.org/licenses/>.
    18  
    19  package bitmine
    20  
    21  import (
    22  	"bytes"
    23  	"encoding/json"
    24  	"fmt"
    25  	"net/url"
    26  
    27  	"github.com/e154/smart-home/common/logger"
    28  )
    29  
    30  var (
    31  	log = logger.MustGetLogger("plugins.cgminer.bitmine")
    32  )
    33  
    34  // Bitmine ...
    35  type Bitmine struct {
    36  	device     DeviceType
    37  	transport  ITransport
    38  	user, pass string
    39  }
    40  
    41  // NewBitmine ...
    42  func NewBitmine(transport ITransport, device, user, pass string) (bitmine *Bitmine, err error) {
    43  
    44  	bitmine = &Bitmine{
    45  		transport: transport,
    46  		user:      url.QueryEscape(user),
    47  		pass:      url.QueryEscape(pass),
    48  	}
    49  
    50  	switch device {
    51  	case DeviceS9.String():
    52  		bitmine.device = DeviceS9
    53  	case DeviceS7.String():
    54  		bitmine.device = DeviceS7
    55  	case DeviceL3.String(), DeviceL3Plus.String():
    56  		bitmine.device = DeviceL3Plus
    57  	case DeviceD3.String():
    58  		bitmine.device = DeviceD3
    59  	case DeviceT9.String():
    60  		bitmine.device = DeviceT9
    61  	default:
    62  		bitmine = nil
    63  		err = fmt.Errorf("unknown device %s", device)
    64  	}
    65  
    66  	return
    67  }
    68  
    69  func (b *Bitmine) checkStatus(statuses []Status) error {
    70  	for _, status := range statuses {
    71  		switch status.Status {
    72  		case "E":
    73  			return fmt.Errorf("API returned error: Code: %d, Msg: '%s', Description: '%s'", status.Code, status.Msg, status.Description)
    74  		case "F":
    75  			return fmt.Errorf("API returned FATAL error: Code: %d, Msg: '%s', Description: '%s'", status.Code, status.Msg, status.Description)
    76  		case "S":
    77  		case "W":
    78  		case "I":
    79  
    80  		}
    81  	}
    82  	return nil
    83  }
    84  
    85  // Stats ...
    86  func (b *Bitmine) Stats() (data []byte, err error) {
    87  
    88  	var commandResponse []byte
    89  	if commandResponse, err = b.transport.RunCommand("stats", ""); err != nil {
    90  		return
    91  	}
    92  
    93  	var resp StatsResponse
    94  	//TODO uncomment in go2
    95  	//switch b.device {
    96  	//case DeviceS9:
    97  	//	resp = StatsResponse[StatsS9]{}
    98  	//case DeviceS7:
    99  	//	resp = StatsResponse[StatsS7]{}
   100  	//case DeviceL3, DeviceL3Plus:
   101  	//	resp = StatsResponse[StatsL3]{}
   102  	//case DeviceD3:
   103  	//	resp = StatsResponse[StatsD3]{}
   104  	//case DeviceT9:
   105  	//	resp = StatsResponse[StatsT9]{}
   106  	//}
   107  
   108  	// fix incorrect json response from miner "}{"
   109  	fixResponse := bytes.Replace(commandResponse, []byte("}{"), []byte(","), 1)
   110  	if err = json.Unmarshal(fixResponse, &resp); err != nil {
   111  		return
   112  	}
   113  	if err = b.checkStatus(resp.Status); err != nil {
   114  		return
   115  	}
   116  	if len(resp.Stats) < 1 {
   117  		err = ErrNoStatsInJsonResponse
   118  		return
   119  	}
   120  	if len(resp.Stats) > 1 {
   121  		err = ErrTooManyStatsInJsonResponse
   122  		return
   123  	}
   124  	data, err = json.Marshal(resp.Stats[0])
   125  	return
   126  }
   127  
   128  // Devs ...
   129  func (b *Bitmine) Devs() (data []byte, err error) {
   130  	var commandResponse []byte
   131  	if commandResponse, err = b.transport.RunCommand("devs", ""); err != nil {
   132  		return
   133  	}
   134  	var resp DevsResponse
   135  	if err = json.Unmarshal(commandResponse, &resp); err != nil {
   136  		return
   137  	}
   138  	if err = b.checkStatus(resp.Status); err != nil {
   139  		return
   140  	}
   141  	data, err = json.Marshal(resp.Devs)
   142  	return
   143  }
   144  
   145  // Summary ...
   146  func (b *Bitmine) Summary() (data []byte, err error) {
   147  	var commandResponse []byte
   148  	if commandResponse, err = b.transport.RunCommand("summary", ""); err != nil {
   149  		return
   150  	}
   151  	var resp SummaryResponse
   152  	if err = json.Unmarshal(commandResponse, &resp); err != nil {
   153  		return
   154  	}
   155  	if err = b.checkStatus(resp.Status); err != nil {
   156  		return
   157  	}
   158  	if len(resp.Summary) > 1 {
   159  		err = ErrReceivedMultipleSummaryObjects
   160  		return
   161  	}
   162  	if len(resp.Summary) < 1 {
   163  		err = ErrNoSummaryInfoReceived
   164  		return
   165  	}
   166  	data, err = json.Marshal(resp.Summary[0])
   167  	return
   168  }
   169  
   170  // Pools ...
   171  func (b *Bitmine) Pools() (data []byte, err error) {
   172  	var commandResponse []byte
   173  	if commandResponse, err = b.transport.RunCommand("pools", ""); err != nil {
   174  		return
   175  	}
   176  	var resp PoolsResponse
   177  	if err = json.Unmarshal(commandResponse, &resp); err != nil {
   178  		return
   179  	}
   180  	if err = b.checkStatus(resp.Status); err != nil {
   181  		return
   182  	}
   183  	data, err = json.Marshal(resp.Pools)
   184  	return
   185  }
   186  
   187  // AddPool ...
   188  func (b *Bitmine) AddPool(url string) (err error) {
   189  	var commandResponse []byte
   190  	if commandResponse, err = b.transport.RunCommand("addpool", fmt.Sprintf("%s,%s,%s", url, b.user, b.pass)); err != nil {
   191  		return
   192  	}
   193  	var resp GenericResponse
   194  	if err = json.Unmarshal(commandResponse, &resp); err != nil {
   195  		return
   196  	}
   197  	if err = b.checkStatus(resp.Status); err != nil {
   198  		return
   199  	}
   200  	return
   201  }
   202  
   203  // Version ...
   204  func (b *Bitmine) Version() (data []byte, err error) {
   205  	var commandResponse []byte
   206  	if commandResponse, err = b.transport.RunCommand("version", ""); err != nil {
   207  		return
   208  	}
   209  	resp := &VersionResponse{}
   210  	if err = json.Unmarshal(commandResponse, resp); err != nil {
   211  		return
   212  	}
   213  	if err = b.checkStatus(resp.Status); err != nil {
   214  		return
   215  	}
   216  	if len(resp.Version) < 1 {
   217  		err = ErrNoVersionInJsonResponse
   218  		return
   219  	}
   220  	if len(resp.Version) > 1 {
   221  		err = ErrTooManyVersionsInJsonResponse
   222  		return
   223  	}
   224  	data, err = json.Marshal(resp.Version[0])
   225  	return
   226  }
   227  
   228  // Enable ...
   229  func (b *Bitmine) Enable(poolId int64) error {
   230  	_, err := b.transport.RunCommand("enablepool", fmt.Sprintf("%d", poolId))
   231  	return err
   232  }
   233  
   234  // Disable ...
   235  func (b *Bitmine) Disable(poolId int64) error {
   236  	_, err := b.transport.RunCommand("disablepool", fmt.Sprintf("%d", poolId))
   237  	return err
   238  }
   239  
   240  // Delete ...
   241  func (b *Bitmine) Delete(poolId int64) error {
   242  	_, err := b.transport.RunCommand("removepool", fmt.Sprintf("%d", poolId))
   243  	return err
   244  }
   245  
   246  // SwitchPool ...
   247  func (b *Bitmine) SwitchPool(poolId int64) error {
   248  	_, err := b.transport.RunCommand("switchpool", fmt.Sprintf("%d", poolId))
   249  	return err
   250  }
   251  
   252  // Restart ...
   253  func (b *Bitmine) Restart() error {
   254  	_, err := b.transport.RunCommand("restart", "")
   255  	return err
   256  }
   257  
   258  // Quit ...
   259  func (b *Bitmine) Quit() error {
   260  	_, err := b.transport.RunCommand("quit", "")
   261  	return err
   262  }
   263  
   264  // Bind ...
   265  func (b *Bitmine) Bind() interface{} {
   266  	return NewBitmineBind(b)
   267  }