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 }