Skip to content

Commit

Permalink
Merge pull request #1 from HandyMiner/feature_hot_plug
Browse files Browse the repository at this point in the history
Feature hot plug
  • Loading branch information
alexsmith540 authored Jul 27, 2020
2 parents def5e9d + 95109a4 commit df501ab
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 34 deletions.
7 changes: 6 additions & 1 deletion mine.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ fs.readFile('./goldshell.json',(err,data)=>{
//we spawn like this because a module in the configurator
//closes the process before the asic shuts down, meaning
//it stays running/messes up the workflows, sheesh..
let minerProcess = spawn('node',[__dirname+'/mine.js'],{env:process.env});
//detect HandyGUI node
let nodeExec = 'node';
if(typeof process.env.HANDYMINER_GUI_NODE_EXEC != "undefined"){
nodeExec = process.env.HANDYMINER_GUI_NODE_EXEC;
}
let minerProcess = spawn(nodeExec,[__dirname+'/mine.js'],{env:process.env});
minerProcess.stdout.pipe(process.stdout);

}).catch(e=>{});
Expand Down
185 changes: 156 additions & 29 deletions miner/HandyMiner_GoldShell.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ class HandyMiner {
this.asicStats = {};
this.asicShares = {};
this.asicWorkQueueNext = {};
this.asicInfoLookupIntervals = {};
this.hasDisplayedZeroAsicMessage = false;
this.didInitialHardwareDetection = false;
this.gpuNames = {};
this.lastGPUHashrate = {};
if(process.argv[2] == '-1'){
Expand Down Expand Up @@ -258,7 +261,6 @@ class HandyMiner {
this.initListeners();
}
startAvgHashrateReporter(){

if(typeof this.lastASICReporterTimeout != "undefined"){
clearTimeout(this.lastASICReporterTimeout);
}
Expand Down Expand Up @@ -329,20 +331,7 @@ class HandyMiner {
}


//kill connection when we kill the script.
//stratum TODO: gracefully handle messy deaths/disconnects from clients else it kills hsd atm.

exitHook((callback)=>{
this.killHandyMiner(callback);
})
process.stdin.on('data', data => {
//from dashboard.js, exitHook wont catch so we use stdin..
if(data.toString('utf8') == 'dashboard sigint'){
this.killHandyMiner().then(()=>{
process.exit(0);
})
}
})
//process.stdin.setRawMode(true);
});
let ongoingResp = '';
Expand Down Expand Up @@ -445,6 +434,9 @@ class HandyMiner {
let p = new Promise((resolve,reject)=>{
let complete = 0;
let len = Object.keys(this.asicWorkers).length;
if(len == 0){
resolve();
}
Object.keys(this.asicWorkers).map(workerID=>{
let resetDeviceParamsBuffer = new Buffer.from('A53C96A21010000000A200000000040000004169C35A','hex');
this.asicWorkers[workerID].write(resetDeviceParamsBuffer,err=>{
Expand Down Expand Up @@ -1169,6 +1161,7 @@ class HandyMiner {
});

},20000);
this.asicInfoLookupIntervals[asicID] = sI;
}
else{
//TODO:::
Expand Down Expand Up @@ -1316,15 +1309,40 @@ class HandyMiner {
let perWorkerRateAvg = {};
let perAsicRateNow = {};
let perAsicRateAvg = {};

Object.keys(this.asicWorkers).map(asicID=>{
/*let sumHashrates = 0;
let sumAverages = 0;
let sumAverageLength = 0;
if(!process.env.HANDYRAW){
Object.keys(this.asicWorkers).map(asicID=>{
//first display sum all
let workDepth = this.asicNames[asicID].workDepth;
for(let workerID=1;workerID<=workDepth;workerID++){
if(typeof this.asicJobHashrates[asicID+'_'+workerID] == "undefined"){
continue;
}
let hashRatePerSecond = this.asicJobHashrates[asicID+'_'+workerID].rate;
sumHashrates += hashRatePerSecond;
let hourlyAvg = this.asicJobHashrates[asicID+'_'+workerID].last200Rates.reduce((a,b)=>{
return a+b;
})/this.asicJobHashrates[asicID+'_'+workerID].last200Rates.length;
sumAverages += hourlyAvg;
sumAverageLength += 1;
}
});
let totalAverageHashrate = sumAverages / sumAverageLength;
}*/
Object.keys(this.asicWorkers).map((asicID,asicI)=>{
perAsicRateNow[asicID] = 0;
perAsicRateAvg[asicID] = 0;
perWorkerRateNow[asicID] = {};
perWorkerRateAvg[asicID] = {};
let workDepth = this.asicNames[asicID].workDepth;
for(let workerID=1;workerID<=workDepth;workerID++){

if(typeof this.asicJobHashrates[asicID+'_'+workerID] == "undefined"){
continue;
}
let hashRatePerSecond = this.asicJobHashrates[asicID+'_'+workerID].rate;
this.asicJobHashrates[asicID+'_'+workerID].last200Rates.push(hashRatePerSecond);
if(this.asicJobHashrates[asicID+'_'+workerID].last200Rates.length >= 200){
Expand All @@ -1333,6 +1351,27 @@ class HandyMiner {
let hourlyAvg = this.asicJobHashrates[asicID+'_'+workerID].last200Rates.reduce((a,b)=>{
return a+b;
})/this.asicJobHashrates[asicID+'_'+workerID].last200Rates.length;

//dont display negative #s
if(hourlyAvg < 0){
hourlyAvg = 0;
}
if(isNaN(hourlyAvg)){
hourlyAvg = 0;
}
if(hourlyAvg == null){
hourlyAvg = 0;
}
if(hashRatePerSecond < 0){
hashRatePerSecond = 0;
}
if(isNaN(hashRatePerSecond)){
hashRatePerSecond = 0;
}
if(hashRatePerSecond == null){
hashRatePerSecond = 0;
}

perAsicRateAvg[asicID] += hourlyAvg;
perAsicRateNow[asicID] += hashRatePerSecond;

Expand All @@ -1353,16 +1392,34 @@ class HandyMiner {
console.log(`\x1b[36m######## WORKERID\x1b[0m: ${workerID}, \x1b[36mNOW\x1b[0m: ${Math.round(perWorkerRateNow[asicID][workerID]*100)/100}GH, \x1b[36mAVG-1HR\x1b[0m: ${Math.round(perWorkerRateAvg[asicID][workerID]*100)/100}GH`);
}
console.log('');
if(asicI == Object.keys(this.asicWorkers).length-1){
//is last, display total

console.log(`\x1b[36m##### TOTAL HASHRATE NOW\x1b[0m: ${Math.round(sumRateNow*100)/100}GH, \x1b[36mAVG-1HR\x1b[0m: ${Math.round((sumRateAvg)*100)/100}GH`);
console.log('');
}
}
else{
let workerHashrates = {};
for(let workerID=1;workerID<=workDepth;workerID++){
let wNow = 0;
let wAvg = 0;

if(typeof perWorkerRateNow[asicID][workerID] != "undefined"){
wNow = Math.round(perWorkerRateNow[asicID][workerID]*100)/100;
wAvg = Math.round(perWorkerRateAvg[asicID][workerID]*100)/100;
}

workerHashrates[workerID] = {
hashrateNow: Math.round(perWorkerRateNow[asicID][workerID]*100)/100,
hashrateAvg: Math.round(perWorkerRateAvg[asicID][workerID]*100)/100
hashrateNow: wNow,
hashrateAvg: wAvg
};
}
//return api output
let lastNonce = '0000000000000000';
if(typeof this.asicJobHashrates[asicID+'_'+1] != "undefined"){
lastNonce = this.asicJobHashrates[asicID+'_'+1].last;
}
let asicData = {
type:'asicStats',
data:{
Expand All @@ -1377,7 +1434,7 @@ class HandyMiner {
hashrateAvg: Math.round(perAsicRateAvg[asicID]*100)/100,
workerHashrates:workerHashrates,
solutions: this.asicShares[asicID],
lastNonce: this.asicJobHashrates[asicID+'_'+1].last
lastNonce: lastNonce
}
}
process.stdout.write(JSON.stringify(asicData)+'\n')
Expand All @@ -1391,6 +1448,9 @@ class HandyMiner {

this.asicWorkQueueNext[asicID] = workerID+1;
let serialConn = this.asicWorkers[asicID];
if(typeof serialConn == "undefined"){
return;
}
//console.log('early on header time is',work.work.header.slice(4,12).toString('hex'));

let tgt = work.work.target.slice(0,8).reverse().toString('hex').slice(0,16).toUpperCase() ;
Expand Down Expand Up @@ -1455,15 +1515,57 @@ class HandyMiner {
this.handleAsicMessage(data,asicID);

})
conn.on('close',data=>{
//was disconnected

delete this.asicWorkers[asicID];
delete this.asicNames[asicID];
if(this.asics.indexOf(asicID) >= 0){
let asicList = this.asics.split(',');
asicList = asicList.filter(id=>{
return id != asicID;
});
if(asicList.length == 0){
this.asics = '-1';
}
else{
this.asics = asicList.join(',');
}
}
if(typeof this.asicInfoLookupIntervals[asicID] != "undefined"){
clearInterval(this.asicInfoLookupIntervals[asicID]);
delete this.asicInfoLookupIntervals[asicID];
}
if(!this.isKilling){
this.startAvgHashrateReporter();
if(process.env.HANDYRAW){
//log error
let errData = {
data:{asicID:asicID},
disconnected:true,
message:'HS1 ['+asicID+'] WAS DISCONNECTED',
type:'error'
};
process.stdout.write(JSON.stringify(errData)+'\n')
}
else{
console.log('\x1b[31mERROR: HS1 ['+asicID+'] WAS DISCONNECTED\x1b[0m')
}
}
})
}
else{

this.listAsics();

}



}
listenForNewHardware(){
setTimeout(()=>{
this.listAsics();
this.listenForNewHardware();
},2000);
}
listAsics(){
//list asics
Expand All @@ -1488,10 +1590,15 @@ class HandyMiner {
//}

foundAsics = [];
if(ports.length == 0){
if(ports.length == 0 && Object.keys(this.asicNames).length == 0 && !this.hasDisplayedZeroAsicMessage){
//no ports found
this.finishCheck(hasPolled,pollCount,asics);
}
ports = ports.filter(p=>{
return Object.keys(this.asicNames).indexOf(p.path) == -1;
});
pollCount = ports.length;

ports.map(port=>{

let p = port.path;
Expand All @@ -1517,13 +1624,12 @@ class HandyMiner {
}
})
conn.on('data',data=>{
hasPolled++;

if(data[3] == 0x54){
let asicInfo = this.goldShellParser.parseASICDeviceInfo(data,p);
asics.push(asicInfo);
}
conn.close(err=>{
hasPolled++;
this.finishCheck(hasPolled,pollCount,asics);
});
//this.finishCheck(hasPolled,pollCount,asics);
Expand All @@ -1547,6 +1653,7 @@ class HandyMiner {
return;
}
if(asics.length == 0){
this.hasDisplayedZeroAsicMessage = true;
if(process.env.HANDYRAW){
let regResp = {
data:[],
Expand All @@ -1557,12 +1664,13 @@ class HandyMiner {
else{
console.log('\x1b[31mERROR: NO GOLDSHELL HS1 FOUND\x1b[0m')
console.log('PLEASE VERIFY THE USB IS PLUGGED IN AND THE ASIC HAS AC POWER')
console.log('SEE https://github.com/HandyMiner/HandyMiner-GoldShell-CLI/ for troubleshooting')
//console.log('SEE https://github.com/HandyMiner/HandyMiner-GoldShell-CLI/ for troubleshooting')
}

process.exit(0);
//process.exit(0);
}
else{
this.hasDisplayedZeroAsicMessage = true; //already displayed them here
if(process.env.HANDYRAW){
/*let regResp = {
data:asics,
Expand All @@ -1582,17 +1690,25 @@ class HandyMiner {
this.asics.split(',').map(s=>{return s.trim();}).map((asicID,asicI)=>{
this.spawnASICWorker(asicID,asicI);
});
setTimeout(()=>{
//after init, give it a few seconds to init the hashrate display
this.tickHashrateDisplay();
},3000);
this.startAvgHashrateReporter();

//process.exit(0);
}
if(!this.didInitialHardwareDetection){
this.didInitialHardwareDetection = true;
this.listenForNewHardware();
}
}
mineBlock(response){
const _this = this;

//this.generateWork(); //prep some work ahead of time for the miner exec to pickup right away on init
if(process.env.HANDYRAW){
process.stdout.write(JSON.stringify({type:'stratumLog',message:'starting miner'})+'\n')
process.stdout.write(JSON.stringify({type:'stratumLog',message:'starting miner, detecting ASICs'})+'\n')
}

if(_this.asics != '-1'){
Expand Down Expand Up @@ -1675,7 +1791,18 @@ class HandyMiner {
fs.writeFileSync(process.env.HOME+'/.HandyMiner/version.txt',mTarget);
}
}

//exit hooks to fire only once
exitHook((callback)=>{
this.killHandyMiner(callback);
})
process.stdin.on('data', data => {
//from dashboard.js, exitHook wont catch so we use stdin..
if(data.toString('utf8') == 'dashboard sigint'){
this.killHandyMiner().then(()=>{
process.exit(0);
})
}
})

this.isMGoing = false;
if(typeof this.mCheck != "undefined"){
Expand Down
Loading

0 comments on commit df501ab

Please sign in to comment.